Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
4743e77
docs: add AI index model & prompt benchmark
bernardladenthin Jun 27, 2026
9b02df4
docs: deepen AI index benchmark (per-file matrix, pros/cons, external…
bernardladenthin Jun 27, 2026
6aaa6fd
feat: per-file prompt-cache reuse and system/user prompt split
bernardladenthin Jun 27, 2026
b7fdd7c
docs: record cache_prompt optimization result (COMPARISON §10)
bernardladenthin Jun 27, 2026
5c457b5
feat: gpt-oss reasoning config (reasoning_format=auto + reasoning_eff…
bernardladenthin Jun 27, 2026
42ced01
feat: make gpt-oss reasoning_effort configurable per model (default low)
bernardladenthin Jun 27, 2026
84b27f1
feat: clean gpt-oss small/medium/high presets sized for large files
bernardladenthin Jun 27, 2026
5f2a576
docs: gpt-oss reasoning_effort table + large-file clean-run validation
bernardladenthin Jun 27, 2026
c81898d
feat: size-tiered gpt-oss presets (c16k/c48k/c96k) for large projects
bernardladenthin Jun 27, 2026
92f569b
docs: large-file context limits, mixed-size strategy, 250KB validatio…
bernardladenthin Jun 27, 2026
604a8b2
docs: add context-size A/B (RAM-vs-time) evidence to §11
bernardladenthin Jun 27, 2026
0a82706
feat: per-file duration estimate (logged ETA) + gpt-oss c96k default
bernardladenthin Jun 27, 2026
fac147c
docs: per-file timing model (O(n^2) prefill) + c96k-default rationale…
bernardladenthin Jun 27, 2026
44041d3
docs: bring READMEs up to date with gpt-oss presets, c96k default, ti…
bernardladenthin Jun 27, 2026
4569404
fix: ASCII-only per-file ETA log and "<1 KB" size label
bernardladenthin Jun 27, 2026
e75d2fd
feat: default the self-index to gpt-oss-20B-c96k
bernardladenthin Jun 27, 2026
f14819b
docs: production default is now gpt-oss-20B-c96k (Qwen = throughput a…
bernardladenthin Jun 27, 2026
cb15ac3
docs(gpt-oss-tuning): Phase 1 — reasoning_effort × budget findings
bernardladenthin Jun 27, 2026
6e04936
docs(gpt-oss-tuning): Phase 2 — temperature sweep findings
bernardladenthin Jun 27, 2026
c655e43
docs(gpt-oss-tuning): Phase 4 — timing-model validation + count-vs-sc…
bernardladenthin Jun 28, 2026
7195556
docs(gpt-oss-tuning): Phase 5 — real-Java chars/token measurement
bernardladenthin Jun 28, 2026
9b13ab8
docs(gpt-oss-tuning): Phase 3 — count-exact prompt fixes large-file m…
bernardladenthin Jun 28, 2026
5e0713d
docs(gpt-oss-tuning): add reusable score.sh harness tool
bernardladenthin Jun 28, 2026
ee25091
feat: add min_p sampling support (config chain + provider)
bernardladenthin Jun 28, 2026
2134fb3
feat: vet-driven gpt-oss defaults — temp 0.7 + min_p 0.05, count-exac…
bernardladenthin Jun 28, 2026
0120286
feat: tune ETA estimator to real Java (4.8 chars/token, 700 template,…
bernardladenthin Jun 28, 2026
07b8c85
docs(gpt-oss-tuning): resolve D1/D2/D3 after 2-round web verification
bernardladenthin Jun 28, 2026
ec427ea
docs(gpt-oss-tuning): Round 3 — adversarial optimality review + on-ma…
bernardladenthin Jun 28, 2026
34fd53d
feat: add top_n_sigma sampling support (config chain + provider), def…
bernardladenthin Jun 28, 2026
b2f0cc6
docs(gpt-oss-tuning): E6 result — top-n-sigma vs min-p, keep min-p
bernardladenthin Jun 28, 2026
1abe873
feat: add swa-full + cache-reuse (model-level) support, default off
bernardladenthin Jun 28, 2026
6ab324e
docs(gpt-oss-tuning): E4 result — swa-full + cache-reuse speeds up ba…
bernardladenthin Jun 28, 2026
4ac9883
feat: add reasoning/think-budget support (per-request), default unres…
bernardladenthin Jun 28, 2026
fff6296
docs(gpt-oss-tuning): E2 result — reasoning budget is a no-op for gpt…
bernardladenthin Jun 28, 2026
d40be48
refactor: remove the empty-body retry mechanism
bernardladenthin Jun 28, 2026
3651c87
feat: add DRY repetition-suppression sampling (per-request), default off
bernardladenthin Jun 28, 2026
dea8127
docs(gpt-oss-tuning): E1 (DRY) + retry-removal note + opt-in knobs re…
bernardladenthin Jun 28, 2026
ab2e6dd
feat: adopt E4 swa-full + cache-reuse as the shipped default
bernardladenthin Jun 28, 2026
b32ec14
feat(E3): file-size band filter for size-tiered indexing
bernardladenthin Jun 28, 2026
d123d9d
docs(gpt-oss-tuning): E5 quantization A/B - quant choice barely matte…
bernardladenthin Jun 28, 2026
38838d5
docs(pom): add gpt-oss-20b quantization menu with E5 measurements
bernardladenthin Jun 28, 2026
b01f0e0
feat: log measured per-file generation time (actual vs estimated)
bernardladenthin Jun 28, 2026
2eaeaca
feat: rule-based file routing — per file model+prompt, with plan tree…
bernardladenthin Jun 28, 2026
d9ddec3
docs(CLAUDE): document rule-based file routing, plan tree, planOnly
bernardladenthin Jun 28, 2026
fbfa98e
feat: plan as Markdown with per-file time estimate, per-model + grand…
bernardladenthin Jun 28, 2026
decd7b6
feat: rule id (label) shown in the plan markdown Rule column
bernardladenthin Jun 29, 2026
2e2a5da
feat: general-purpose condition tree for routing rules (and/or/not + …
bernardladenthin Jun 29, 2026
afa462e
docs(CLAUDE): document the condition tree routing (and/or/not + leaves)
bernardladenthin Jun 29, 2026
843def5
fix: refine nullable rule id to a local in AiIndexPlan.ruleId
bernardladenthin Jun 29, 2026
a19c27a
fix: bind and/or via an AiConditionGroup so Maven accepts <conditions…
bernardladenthin Jun 29, 2026
a6515f3
docs(TODO): sync PIT count (426/100%) + record routing/condition + gp…
bernardladenthin Jun 29, 2026
0188563
feat: add gpuLayers (--gpu-layers) config knob, default -1 (leave bui…
bernardladenthin Jun 29, 2026
96904a5
feat: opt-in gpu-cuda / gpu-vulkan profiles + parameterized native cl…
bernardladenthin Jun 29, 2026
623f8a2
docs(README): correct GPU enablement — lib.path is the reliable path
bernardladenthin Jun 29, 2026
eec05ab
feat: add mainGpu / devices GPU-selection knobs + document plugin-dep…
bernardladenthin Jun 29, 2026
858e402
feat(pom): default to gpt-oss-20B-mxfp4 + make all gpt-oss presets GP…
bernardladenthin Jun 29, 2026
90a13f2
build(spotbugs): suppress fb-contrib opinion findings on the routing/…
bernardladenthin Jun 29, 2026
d28faf9
docs(tuning): E2 build-11 CUDA re-test — high-effort blackhole gone, …
bernardladenthin Jun 29, 2026
36b7a8e
docs+build: consistency pass before final push (default model, versio…
bernardladenthin Jun 29, 2026
3aed439
feat: plan-time context-window check + fail-fast on oversized files
bernardladenthin Jun 29, 2026
39e5fa6
refactor: over-window is always a hard failure (config-only fallback,…
bernardladenthin Jun 29, 2026
625fc3e
feat: per-file progress bar + ETA during the generate run
bernardladenthin Jun 29, 2026
5223b0f
fix: drop double tilde in the progress line's "left" estimate
bernardladenthin Jun 29, 2026
0dfaa30
feat(pom): big-window fallback = IBM Granite 4.0-H-Tiny (Apache-2.0),…
bernardladenthin Jun 29, 2026
d5e17ff
feat(pom): big-window fallback covers up to ~1 MB (Granite at 384K, v…
bernardladenthin Jun 29, 2026
857e404
docs(TODO): sync — drop completed history, list only open items
bernardladenthin Jun 29, 2026
9cd3b20
docs(README): fully document the per-model <aiDefinition> parameters
bernardladenthin Jun 29, 2026
b1a02d5
build: pin net.ladenthin:llama to the released 5.0.3 (drop SNAPSHOT +…
bernardladenthin Jun 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,15 @@ replay_pid*

# jcstress / jqwik test outputs (generated in repo root)
/.jqwik-database

# Benchmark/experiment scratch output dirs (not part of the build)
src/siteGusto/
src/siteMistral3/
src/siteQwenBRUTAL/

# IDE config
.idea/

# Generated AI-index output from the self-index run (keep the tracked placeholder)
/src/site/ai/*
!/src/site/ai/empty.md
37 changes: 33 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ This document provides guidance for AI assistants working on the llamacpp-ai-ind

- **Group ID:** `net.ladenthin`
- **Artifact ID:** `llamacpp-ai-index-maven-plugin`
- **Version:** 1.0.0
- **Version:** 1.0.1-SNAPSHOT
- **Java:** target bytecode 1.8, built with JDK 21
- **License:** Apache 2.0
- **Author:** Bernard Ladenthin (Copyright 2026)
Expand Down Expand Up @@ -126,6 +126,27 @@ The plugin operates in three logical phases, building a navigable index from fin
```
[Source .java files] → SourceFileIndexer → [*.java.ai.md files (deterministic header + AI body)]
```
The `generate` goal is **plan-then-execute** and **rule-routed**: it first walks all candidate files,
routes each via the `<fieldGeneration>` rules to a `(model, prompt)` — or a *skip*, or the explicit
*fallback* — and logs a tree grouped by model (which file gets which model + prompt). It then loads
**each model once** (groups sharing an `aiDefinitionKey`, sequentially → one model resident at a time,
bounded RAM) and indexes that group's files. A rule matches by a composable **`<condition>` tree** — `<and>`/`<or>` (each wraps its children in
`<conditions><condition>…</condition></conditions>`), `<not>` (a single nested condition), over leaves
`<extensions>`, `<size>` (`min`/`max` bytes), `<lines>` (`min`/`max`), `<modifiedAfter>`/`<modifiedBefore>`
(ISO-8601 instant vs file mtime), `<pathGlob>` (base-relative glob) — evaluated by `AiConditionEvaluator`
against an `AiFileContext`; new leaf kinds are one field + one branch. Among matches the highest
`priority` wins (ties by declaration order). `<skip>true</skip>` ignores matching files (a high-priority
skip beats routes and the fallback); exactly one `<fallback>true</fallback>` (no condition) catches the
rest; a file matching no rule and no fallback **fails the build**. `aiIndex.planOnly=true` prints the
Markdown plan (file → rule id → prompt → rough time estimate, summed per model and overall) and stops
(no model loaded). The plan also computes each routed file's **context-window fit** up front (via
`AiInputWindowCalculator`, the same threshold the run uses to trim): a file larger than its routed
model's window is flagged in the plan and **always fails the build** (a hard abort). The resolution is
**configuration only** — the plugin never auto-picks a model: the user must add a `<fieldGeneration>`
rule with a size `<condition>` that routes oversized files to a model with a large enough context window
(see the big-window fallback example in the POM). See `AiFieldGenerationSelector` (selection + validation), `AiCondition`/
`AiConditionEvaluator` (the tree), and `AiIndexPlan` (the rendered plan). This is how one run can index
different file kinds/sizes with different models *and* prompts.

**Phase 2 — Package Aggregation & Summarization**
```
Expand Down Expand Up @@ -163,7 +184,12 @@ the top of `execute()`. Covered by `MojoPhaseSkipTest`.
| `GenerateMojo` | Phase 1: index + summarize source files |
| `AggregatePackagesMojo` | Phase 2: aggregate + summarize package index files |
| `AggregateProjectMojo` | Phase 3: build the single `project.ai.md` (deterministic listing; extends `AbstractAiIndexMojo` and builds a provider **only** when a `<fieldGeneration>` opts into the AI overview) |
| `SourceFileIndexer` | Walks source trees, creates `.ai.md` files, calls AI to fill the document body |
| `SourceFileIndexer` | `collectCandidates` (walk + filters) / `classify` (→ `AiIndexPlan`) / `indexFile` (write one file with a given rule + provider) — split so a run plans first and loads one model per group |
| `AiFieldGenerationSelector` | Routes a file to a rule by its `<condition>` + priority; explicit fallback; `skip`; plus `validate(rules)` (fail-fast config check) |
| `AiCondition` / `AiConditionEvaluator` | Composable and/or/not condition tree (leaves: extensions/size/lines/modifiedAfter/modifiedBefore/pathGlob) + its evaluator (`matches`/`validate`/`usesLines`) |
| `AiIndexPlan` | The routing plan: routes grouped by model id, skips, unmatched, per-file context-window fit; renders the up-front tree |
| `AiInputWindowCalculator` | Pure calculator for the input window (max source chars before trimming + whether a source exceeds it); single source of truth shared by the run-time trim (`AiFieldGenerationSupport`) and the plan-time over-window check (`SourceFileIndexer.classify`) |
| `AiProgressBar` | Pure ASCII progress-bar renderer (`[##### ] 42%`); `GenerateMojo` logs it after each file, advancing by the running sum of per-file plan estimates over the grand total (with estimated time left + actual elapsed) |
| `PackageIndexer` | Creates `package.ai.md` files with contents listings, calls AI to fill the document body |
| `ProjectIndexer` | Phase 3: harvests each package's lead + relative link into one `project.ai.md`; deterministic listing, with an optional one-call AI `#### Overview` from the leads |
| `AiMdLeadExtractor` | Pure extraction of the one-line blockquote lead from an `.ai.md` body (fallback: first non-blank line) |
Expand Down Expand Up @@ -253,6 +279,9 @@ header block, so a `- F:` line in the body is never read as a link.
| `subtrees` | `aiIndex.subtrees` | *(all)* | Limit to specific source subdirectories |
| `fileExtensions` | `aiIndex.fileExtensions` | `.java` | File extensions to index |
| `excludes` | `aiIndex.excludes` | *(none)* | Glob patterns (base-relative, `/` separators) for source files to skip, e.g. `**/package-info.java`, `**/generated/**` (`AiSourceExcludeFilter`) |
| `minFileSizeBytes` | `aiIndex.file.minSizeBytes` | `0` | Exclusive lower size bound; files `<=` this are skipped (`0` = no lower bound). For size-tiering across multiple `generate` executions |
| `maxFileSizeBytes` | `aiIndex.file.maxSizeBytes` | `0` | Inclusive upper size bound; files `>` this are skipped (`0` = unlimited). Pairs with `minFileSizeBytes` to form a band |
| `planOnly` | `aiIndex.planOnly` | `false` | Print the routing plan tree (model → files → prompt → window fit) and stop; no model loaded, nothing generated |
| `generationProvider` | `aiIndex.generationProvider` | `mock` | `mock` or `llamacpp-jni` |
| `llamaModelPath` | `aiIndex.llama.modelPath` | — | Path to GGUF model file |
| `llamaContextSize` | `aiIndex.llama.contextSize` | `2048` | Context window size |
Expand Down Expand Up @@ -326,7 +355,7 @@ Immutable value types are implemented as Java `record` types (e.g., `AiMdDocumen

| Dependency | Version | Purpose |
|---|---|---|
| `net.ladenthin:llama` | 5.0.2 | llama.cpp JNI binding (GGUF inference); pinned to the layered-package + immutable-wither API. Brings `slf4j-api` transitively, converged to 2.0.18 via `<dependencyManagement>`. |
| `net.ladenthin:llama` | 5.0.3 | llama.cpp JNI binding (GGUF inference); released on Maven Central, carries the prompt-cache/slot APIs + GPU classifier jars. Brings `slf4j-api` transitively, converged to 2.0.18 via `<dependencyManagement>`. |
| `org.apache.maven:maven-plugin-api` | 3.9.13 | Maven plugin API (provided) |
| `org.apache.maven.plugin-tools:maven-plugin-annotations` | 3.15.1 | `@Mojo`, `@Parameter` annotations (provided) |

Expand Down Expand Up @@ -368,7 +397,7 @@ See [`../workspace/workflows/pull-request-workflow.md`](../workspace/workflows/p
3. **Incremental updates** — files with existing summaries are skipped unless `force=true`; checksums detect source changes.
4. **Unified indexing and summarization** — each indexer (`SourceFileIndexer`, `PackageIndexer`) both creates the `.ai.md` skeleton and fills in AI fields in a single pass; no separate summarization step is needed.
5. **Provider abstraction** — AI backends are pluggable through `AiGenerationProvider`; mock provider enables fully deterministic tests.
6. **Configuration-driven prompts** — prompt templates are defined in POM configuration, not hardcoded in Java; changing a prompt requires no code change. For the `generate` goal the per-file prompt is chosen by source extension (`AiFieldGenerationSelector`): each `<fieldGeneration>` may carry an optional `<fileExtensions>` filter (e.g. `.java`/`.sql`), and an entry without one is the fallback — so a Java prompt, a SQL-schema prompt, and a generic fallback can coexist while one model stays loaded.
6. **Configuration-driven prompts & rule-based routing** — prompt templates are defined in POM configuration, not hardcoded in Java; changing a prompt requires no code change. For the `generate` goal each `<fieldGeneration>` is a routing **rule** (`AiFieldGenerationSelector`): a composable `<condition>` tree (`<and>`/`<or>`/`<not>` over leaves extensions/size/lines/modifiedAfter/modifiedBefore/pathGlob — `AiCondition`/`AiConditionEvaluator`), a `<priority>` (highest matching wins, ties by order), and a kind — route (`<promptKey>`+`<aiDefinitionKey>`), `<skip>true</skip>` (ignore), or exactly one explicit `<fallback>true</fallback>`. So one run can route different file kinds/sizes to different models **and** prompts; the model id (`aiDefinitionKey`) carries the full parameter set (path, context, sampling…), and the run loads each model once. A file matching no rule and no fallback fails the build; `aiIndex.planOnly=true` previews the plan tree without loading a model. Prompts live once in a shared plugin-level `<promptDefinitions>` and are referenced by id across all rules/executions (no duplication).

## Javadoc Conventions

Expand Down
Loading
Loading