Skip to content

Commit 1470182

Browse files
aksOpsclaude
andcommitted
docs(claude+summary): close out sub-project 1 plan tasks 40 + 41
Plan §40 / §41 close-out — the resolver SPI, Confidence schema, CACHE_VERSION bump, and runtime lifecycle gotchas now land in CLAUDE.md and PROJECT_SUMMARY.md, not just CHANGELOG.md. CLAUDE.md Gotchas: - Cache versioning bullet updated 4 → 5 with reason (Confidence/source schema), so future agents reading the gotcha don't propagate the stale "4" forward. - "Symbol resolver runs at index-time only" — bootstrapResolvers and resolveFor are wired into run / runBatchedIndex / runSmartIndex only. Never reached at serve. Prevents future agents from reaching for ResolverRegistry from serve-mode code paths. - "Confidence + source mandatory on every CodeNode/CodeEdge" — DetectorEmissionDefaults stamps the floor; RESOLVED is opt-in via ctx.resolved(). Reading legacy data is non-throwing. - "JavaSymbolResolver.resolve() allocates a fresh JavaParser per call" — intentional thread-safety boundary for virtual-thread fan-out, not a perf bug. - "Strict parse-success check" — resolve(String) returns EmptyResolved on any JavaParser problem so the graph never carries phantom RESOLVED-tier edges from partial-CU outputs. - "Volatile fields on JavaSymbolResolver" — closes the public-accessor visibility race per the dual-agent brainstorm fix. PROJECT_SUMMARY.md: - Tech-stack row updated to "AST + symbols (Java) | JavaParser 3.28.0 + javaparser-symbol-solver-core 3.28.0". - Cache dir line updated CACHE_VERSION=4 → 5. - Two new gotchas (resolver-is-index-time-only, strict parse-success) cross-referencing the canonical CLAUDE.md entries. No source changes. Full mvn test was last green at 3618 / 0 / 32 skipped (unchanged for this docs-only commit). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent d2595b6 commit 1470182

2 files changed

Lines changed: 11 additions & 4 deletions

File tree

CLAUDE.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,12 @@ bean for code paths that haven't been ported yet.
421421
- **`@ActiveProfiles("test")`**: Required on any `@SpringBootTest` to avoid Neo4j startup conflicts.
422422
- **Dead code detection**: Must filter by semantic edges only (calls, imports, depends_on). Exclude structural edges (contains, defines) and entry points (endpoints, config files).
423423
- **H2 reserved words**: `key`, `value`, `order` are reserved in H2 SQL. Use `meta_key`, `meta_value` etc. in CREATE TABLE statements.
424-
- **Cache versioning**: `AnalysisCache` has a `CACHE_VERSION` constant (currently `4`). Bump it when changing the hash algorithm or H2 schema so stale caches are auto-cleared on next run.
424+
- **Cache versioning**: `AnalysisCache` has a `CACHE_VERSION` constant (currently `5`, bumped from `4` for the resolver `confidence` + `source` schema). Bump it when changing the hash algorithm, H2 schema, or any field that becomes mandatory on cached nodes/edges so stale caches are auto-cleared on next run.
425+
- **Symbol resolver runs at index-time only.** `Analyzer.bootstrapResolvers()` and `Analyzer.resolveFor()` are wired into `run` / `runBatchedIndex` / `runSmartIndex` paths only — never at `serve`. The resolver SPI lives under `intelligence/resolver/`. If you find yourself reaching for `ResolverRegistry` from a serve-mode code path, stop — the graph is the source of truth at serve.
426+
- **`Confidence` + `source` are mandatory on every `CodeNode` / `CodeEdge`.** `DetectorEmissionDefaults.applyDefaults` stamps the per-detector floor (`LEXICAL` for regex bases, `SYNTACTIC` for AST/JavaParser/structured bases) at the orchestration boundary; detectors that consume `ctx.resolved()` upgrade to `Confidence.RESOLVED` and attach a `target_fqn` property. Reading legacy data without these fields is non-throwing — they read back as `LEXICAL` / null.
427+
- **`JavaSymbolResolver.resolve()` allocates a fresh `JavaParser` per call.** JavaParser instances aren't thread-safe and `resolve()` is invoked from virtual threads concurrently. Per-call allocation is intentional, not a perf bug — don't "optimize" by sharing one parser across calls.
428+
- **`JavaSymbolResolver.resolve(String)` enforces strict parse-success.** When JavaParser flags any problem (`!parseResult.isSuccessful()`), the resolver returns `EmptyResolved.INSTANCE` rather than a partial-CU `JavaResolved`. This prevents silent simple-name-only edges from broken parses that look like RESOLVED-tier coverage. Detectors must treat `ctx.resolved()` returning `EmptyResolved` as "lexical fallback" — never assume RESOLVED edges land for every Java file.
429+
- **`JavaSymbolResolver` fields are `volatile`.** `combined` and `solver` are written by `bootstrap()` and read by `resolve()` + the public accessors from arbitrary virtual-thread carriers. The JLS Thread Start Rule covers the `executor.submit()` path; `volatile` covers post-bootstrap callers on other threads. Don't drop the keyword.
425430
- **FileHasher uses SHA-256**: Changed from MD5. Hash output is 64 hex chars (not 32). Tests must expect 64-char hashes.
426431
- **SnakeYAML parses `on` as Boolean.TRUE**: In YAML files, bare `on` key becomes `Boolean.TRUE`. Use `String.valueOf(key)` comparisons, not `Boolean.TRUE.equals(key)` (SonarCloud S2159).
427432
- **Regex possessive quantifiers**: Use `*+` instead of `*` for nested quantifiers like `([^"\\]*(?:\\.[^"\\]*)*)``([^"\\]*+(?:\\.[^"\\]*+)*+)` to prevent stack overflow (SonarCloud S5998).

PROJECT_SUMMARY.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Read directly from the `pom.xml` `<properties>` block and `src/main/frontend/pac
2323
| Graph DB | Neo4j Embedded 2026.02.3 (Community) | `pom.xml` `<neo4j.version>` |
2424
| MCP | Spring AI 2.0.0-M3 (`spring-ai-starter-mcp-server-webmvc`) | `pom.xml` `<spring-ai.version>` |
2525
| CLI | Picocli 4.7.7 (`picocli-spring-boot-starter`) | `pom.xml` `<picocli.version>` |
26-
| AST (Java) | JavaParser 3.28.0 | `[CLAUDE.md]``pom.xml` references via dep |
26+
| AST + symbols (Java) | JavaParser 3.28.0 + `javaparser-symbol-solver-core` 3.28.0 (Apache-2.0) | `pom.xml` `javaparser` deps; `intelligence/resolver/java/JavaSymbolResolver.java` |
2727
| Parsers (35+ langs) | ANTLR 4.13.2 (TS/JS, Python, Go, C#, Rust, C++) | `[CLAUDE.md]` |
2828
| Cache | H2 in embedded mode (incremental analysis cache) | `src/main/java/io/github/randomcodespace/iq/cache/AnalysisCache.java` |
2929
| Frontend | React 18.3 + AntD 5.24 + ECharts 5.6 + react-router 7 | `src/main/frontend/package.json` |
@@ -114,7 +114,7 @@ CI gate is `mvn verify` — runs unit + integration tests **plus** SpotBugs and
114114
**Required env / external services:** none. codeiq is offline-first by design — Neo4j and H2 are embedded; no external server, no network calls at runtime. Air-gapped install: `git clone` + Maven mirror + `mvn package`. See [`shared/runbooks/first-time-setup.md`](shared/runbooks/first-time-setup.md).
115115

116116
**Cache + graph dirs at runtime** (created in your scanned repo):
117-
- `.codeiq/cache/` — H2 incremental analysis cache (`CACHE_VERSION=4` constant near the top of `cache/AnalysisCache.java`)
117+
- `.codeiq/cache/` — H2 incremental analysis cache (`CACHE_VERSION=5` constant near the top of `cache/AnalysisCache.java`; bumped from 4 for the resolver `confidence` + `source` schema, so stale v4 caches drop and rebuild on first run after upgrade)
118118
- `.codeiq/graph/graph.db/` — Neo4j Embedded data dir
119119

120120
## Conventions an agent must respect
@@ -138,7 +138,9 @@ CI gate is `mvn verify` — runs unit + integration tests **plus** SpotBugs and
138138
- **Edges must be attached to source nodes before `bulkSave()`.** Cypher `MATCH` silently returns 0 rows for missing source IDs — pre-validate.
139139
- **`@ActiveProfiles("test")` is required on every `@SpringBootTest`** to avoid Neo4j auto-startup conflicts.
140140
- **`AnalysisCache` uses a `ReentrantReadWriteLock`** (not `synchronized`). JEP 491 (Java 25) means lock primitives no longer pin virtual-thread carriers; the read/write lock is what prevents `ClosedChannelException` on H2's MVStore under concurrent virtual-thread access. Don't "simplify" to `synchronized`.
141-
- **Bump `CACHE_VERSION` in `cache/AnalysisCache.java`** (top of file) when you change the file-hash algorithm or H2 schema. Stale caches auto-clear on next run.
141+
- **Bump `CACHE_VERSION` in `cache/AnalysisCache.java`** (top of file) when you change the file-hash algorithm or H2 schema. Stale caches auto-clear on next run. Currently `5` (bumped from 4 for the resolver `confidence` + `source` schema).
142+
- **Symbol resolver is index-time only.** `Analyzer.bootstrapResolvers()` is reached from `run` / `runBatchedIndex` / `runSmartIndex` only — never at `serve`. The SPI lives at `intelligence/resolver/`; the Java backend wraps `javaparser-symbol-solver-core`. RESOLVED-tier edges and `target_fqn` properties land at index-time and are then served read-only from Neo4j.
143+
- **`JavaSymbolResolver.resolve(String)` enforces strict parse-success.** Partial-CU outputs from JavaParser problems are converted to `EmptyResolved` so the graph never carries phantom RESOLVED edges from broken parses. Detectors must handle `EmptyResolved` as "lexical fallback".
142144
- **SnakeYAML parses bare `on` as `Boolean.TRUE`.** Compare YAML keys with `String.valueOf(key)`, not `Boolean.TRUE.equals(key)` (SonarCloud S2159).
143145
- **Determinism gate:** every new detector needs a determinism test (run twice, assert equal output) — see existing `*DetectorTest.java` for the pattern.
144146
- **First `mvn verify` downloads ~1 GB NVD database** for OWASP dependency-check. Override locally with `-Ddependency-check.skip=true`.

0 commit comments

Comments
 (0)