diff --git a/.gitignore b/.gitignore index f4d4bc4..1d16974 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,8 @@ target/ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* replay_pid* +# heap dumps from OOM (e.g. -XX:+HeapDumpOnOutOfMemoryError on test/PIT forks) +*.hprof # jcstress / jqwik test outputs (generated in repo root) /.jqwik-database diff --git a/CLAUDE.md b/CLAUDE.md index a3461e3..d626f5a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -99,9 +99,9 @@ llamacpp-ai-index-maven-plugin/ │ │ │ # AiGenerationRequest, AiGenerationResult (carry an AiMdHeader) │ │ ├── prompt/ # AiPromptDefinition, AiPreparedPrompt, AiPromptSupport, AiPromptPreparationSupport │ │ ├── config/ # AiGenerationConfig, AiGenerationKind, AiFieldGenerationConfig, -│ │ │ # AiModelDefinition, AiModelDefinitionSupport +│ │ │ # AiFieldGenerationSelector, AiModelDefinition, AiModelDefinitionSupport │ │ └── support/ # Foundation: AiChecksumSupport, AiTimeSupport, AiPathSupport, -│ │ # Java8CompatibilityHelper, ConvertToRecord +│ │ # AiSourceExcludeFilter, Java8CompatibilityHelper, ConvertToRecord │ ├── site/ │ │ └── ai/ # Output directory for .ai.md files │ └── test/ @@ -118,9 +118,9 @@ llamacpp-ai-index-maven-plugin/ ## Core Architecture -### Two-Phase Operation +### Three-Phase Operation -The plugin operates in two logical phases: +The plugin operates in three logical phases, building a navigable index from fine to coarse: **Phase 1 — File Indexing & Summarization** ``` @@ -132,15 +132,41 @@ The plugin operates in two logical phases: [*.java.ai.md files] → PackageIndexer → [package.ai.md files (deterministic header + AI body)] ``` +**Phase 3 — Project Index (deterministic listing; optional AI overview)** +``` +[package.ai.md files] → ProjectIndexer → [one project.ai.md: per-package lead (body) + link (header F)] +``` +Phase 3 harvests the one-sentence blockquote lead each `package.ai.md` already begins with +(via `AiMdLeadExtractor`) and writes a single, always-loadable table of contents linking to +every package — the entry point an agent reads first to navigate project → package → file → raw. +The per-package listing calls no model, so it is cheap and scales to hundreds of packages (no +embeddings/vector DB). **Optional (opt-in):** when a `` is configured on the +goal, *one* extra AI call writes a short `#### Overview` paragraph from the package leads (never +the full bodies). Incrementality is preserved by folding the overview generation signature +(`promptKey:aiDefinitionKey`) — not the AI output — into the `c` checksum, so an unchanged project +is never re-inferred but enabling/switching the overview, or a package change, rebuilds it. + +**Each phase is independently switchable.** Every goal is a separate Maven execution, and each can be +toggled on/off on its own via a phase-specific skip flag named after the index level (`aiIndex.file.skip`, +`aiIndex.package.skip`, `aiIndex.project.skip` — the `x` node types), with `aiIndex.skip` as a global +"skip all" switch — so you can run nothing, all three, or any subset (e.g. file + project only). The +mechanism is generalized symmetrically: `AbstractAiIndexMojo` owns the global `skip`, the abstract +`isPhaseSkipped()` seam, and `shouldSkip() = skip || isPhaseSkipped()`; each concrete mojo adds exactly +one `skip` `@Parameter` plus a one-line `isPhaseSkipped()` override and calls `shouldSkip()` at +the top of `execute()`. Covered by `MojoPhaseSkipTest`. + ### Key Components | Class | Role | |---|---| -| `AbstractAiIndexMojo` | Shared `@Parameter` fields and utilities for all mojos | +| `AbstractAiIndexMojo` | Shared `@Parameter` fields and utilities for the AI generate/aggregate-packages mojos | | `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 `` opts into the AI overview) | | `SourceFileIndexer` | Walks source trees, creates `.ai.md` files, calls AI to fill the document body | | `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) | | `AiGenerationProvider` | Interface for AI backends (llama.cpp JNI or mock) | | `AiFieldGenerationSupport` | Shared field-generation loop extracted from both indexers | | `AiGenerationResult` | Immutable carrier for the AI-generated body text out of the loop | @@ -156,24 +182,30 @@ The plugin operates in two logical phases: Each `.ai.md` file begins with a metadata header block: ``` - -This class handles parsing of Markdown headers... +### main/java/com/example +- H: 1.0 +- C: A1B2C3D4 +- D: 2026-01-01T00:00:00Z +- T: 2026-01-01T00:01:00Z +- G: 0.1.0 +- A: 1.0.0 +- X: package +- F: [MyClass.java](MyClass.java.ai.md) +- F: [sub/](sub/package.ai.md) +--- +> Handles example domain logic for ... (AI-generated body text continues here) ``` The header carries only deterministic metadata. All AI-generated -content lives in the document body after the header block, keeping +content lives in the document body after the `---` separator, keeping the header machine-parseable without AI involvement (see -`AiMdHeader.java` Javadoc for the rationale). +`AiMdHeader.java` Javadoc for the rationale). The repeatable `F` field +holds the deterministic child links — for a `package`, one per child +`.ai.md` (files and sub-packages); for a `project`, one per package — +so navigation (project → package → file) stays uniformly in the header +while the body stays free-form. `AiMdDocumentCodec` parses only the +header block, so a `- F:` line in the body is never read as a link. | Field | Meaning | |---|---| @@ -184,7 +216,8 @@ the header machine-parseable without AI involvement (see | `t` | Last generation timestamp | | `g` | Plugin version (`project.version`) | | `a` | AI model version | -| `x` | Node type: `file` or `package` | +| `x` | Node type: `file`, `package`, or `project` | +| `F` | Repeatable child link (markdown), e.g. `[Foo.java](Foo.java.ai.md)`; the navigation list for `package`/`project` nodes, absent for `file` | ### Provider Pattern @@ -205,16 +238,21 @@ the header machine-parseable without AI involvement (see |---|---| | `ai-index:generate` | Phase 1: index source files and fill the AI-generated document body | | `ai-index:aggregate-packages` | Phase 2: aggregate package index files and fill the AI-generated document body | +| `ai-index:aggregate-project` | Phase 3: harvest per-package leads into one `project.ai.md` (deterministic listing; optional one-call AI `#### Overview` when a `` is configured) | ### Key Parameters (`GenerateMojo`) | Parameter | Property | Default | Description | |---|---|---|---| | `outputDirectory` | `aiIndex.outputDirectory` | `${basedir}/src/site/ai` | Where `.ai.md` files are written | -| `skip` | `aiIndex.skip` | `false` | Skip all execution | +| `skip` | `aiIndex.skip` | `false` | Global switch: skip **every** phase | +| `skipFile` | `aiIndex.file.skip` | `false` | Skip only the **file** phase (`generate` goal) | +| `skipPackage` | `aiIndex.package.skip` | `false` | Skip only the **package** phase (`aggregate-packages` goal) | +| `skipProject` | `aiIndex.project.skip` | `false` | Skip only the **project** phase (`aggregate-project` goal) | | `force` | `aiIndex.force` | `false` | Regenerate even if summary exists | | `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`) | | `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 | @@ -330,7 +368,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. +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 `` may carry an optional `` 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. ## Javadoc Conventions diff --git a/README.md b/README.md index b86f1a6..410c594 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ [![Coverage Status](https://coveralls.io/repos/github/bernardladenthin/llamacpp-ai-index-maven-plugin/badge.svg?branch=main)](https://coveralls.io/github/bernardladenthin/llamacpp-ai-index-maven-plugin?branch=main) [![codecov](https://codecov.io/gh/bernardladenthin/llamacpp-ai-index-maven-plugin/graph/badge.svg)](https://codecov.io/gh/bernardladenthin/llamacpp-ai-index-maven-plugin) [![JaCoCo](https://img.shields.io/codecov/c/github/bernardladenthin/llamacpp-ai-index-maven-plugin?label=JaCoCo&logo=java)](https://codecov.io/gh/bernardladenthin/llamacpp-ai-index-maven-plugin) -[![PIT Mutation](https://img.shields.io/badge/PIT%20mutation-100%25%20(1%20class)-brightgreen)](https://github.com/bernardladenthin/llamacpp-ai-index-maven-plugin/actions/workflows/publish.yml) +[![PIT Mutation](https://img.shields.io/badge/PIT%20mutation-100%25%20(24%20classes)-brightgreen)](https://github.com/bernardladenthin/llamacpp-ai-index-maven-plugin/actions/workflows/publish.yml) **Quality:** [![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=bernardladenthin_llamacpp-ai-index-maven-plugin&metric=alert_status)](https://sonarcloud.io/dashboard?id=bernardladenthin_llamacpp-ai-index-maven-plugin) @@ -76,14 +76,18 @@ using the assigned ID: A Maven plugin for generating hierarchical, AI-readable documentation of source code projects using local llama.cpp-compatible models. It creates structured `.ai.md` files per source file and aggregates them into package-level summaries for fast semantic navigation and retrieval. ## Features -- Generate AI summaries for Java source files +- Generate AI summaries for source files +- Per-language prompts — Java, SQL schema, and a generic fallback — selected by file extension - Weave searchable type, API and domain names into every summary - Aggregate summaries at package level +- Build a single project index (one line + link per package) for top-down navigation, optionally with a one-call AI `#### Overview` +- Run any phase independently — toggle file / package / project on or off +- Exclude trivial or generated files with glob patterns - Uses local models via llama.cpp (no cloud dependency) - Incremental updates (skips unchanged files) - Optimized for AI-assisted code understanding ## How It Works -The plugin runs in two phases. +The plugin runs in three phases, building a navigable index from fine to coarse. ### 1. File Generation (generate) - Scans configured source directories - Creates `.ai.md` files per source file @@ -91,7 +95,14 @@ The plugin runs in two phases. ### 2. Package Aggregation (aggregate-packages) - Traverses generated `.ai.md` files - Builds hierarchical package summaries -- Produces `package.ai.md` files +- Produces `package.ai.md` files; the header carries a deterministic `F` link list to each child (package → file navigation) +### 3. Project Index (aggregate-project) +- Harvests the one-line lead from every `package.ai.md` — the per-package listing is deterministic, no AI call +- Produces a single `project.ai.md`: one body line per package (its lead) with the clickable links in the header `F` list +- A compact, always-loadable table of contents an agent reads first to navigate down +- **Optional** (opt-in): configure a `` on this goal and it makes *one* extra AI call to + write a short `#### Overview` paragraph from the package leads. The deterministic per-package listing is + unchanged; with no field generation the goal stays purely deterministic and calls no model. ## Example Output ``` ### AiMdDocument.java @@ -138,9 +149,13 @@ The plugin is configured from three building blocks, declared on the plugin insi 1. **``** — define each GGUF model once (path + sampling parameters), each with a ``. 2. **``** — define each prompt template once, each with a ``. A template takes - two `%s` placeholders: the file/package name and the source (or, for packages, the child summaries). + two `%s` placeholders: the file/package name and the source (for packages, the child summaries; for + the optional project overview, the per-package leads). 3. **``** — per goal, map one `` to one ``. This is - **required**: a goal with no field generation fails fast. + **required**: a goal with no field generation fails fast. The `generate` goal may list several + field generations and give each an optional `` filter so the per-file prompt is + chosen by source language (`.java` → a Java prompt, `.sql` → a SQL-schema prompt); an entry with + no `` is the fallback applied to any file no extension-specific entry matched. ```xml @@ -168,11 +183,22 @@ The plugin is configured from three building blocks, declared on the plugin insi - + - file-body + file-body-java + + + + file-body-fallback + + + + project-body + @@ -199,9 +234,19 @@ File summaries: generate-resources generate + - file-body + file-body-java + coder + + .java + + + + file-body-fallback coder @@ -220,6 +265,22 @@ File summaries: + + + ai-aggregate-project + prepare-package + aggregate-project + + + + project-body + coder + + + + ``` @@ -237,9 +298,20 @@ Run-level parameters (set in ``): - `outputDirectory` — target directory for `.ai.md` files (default: `${project.basedir}/src/site/ai`) - `subtrees` — source directories to index, relative to the project base dir (default: `src/main/java`) - `fileExtensions` — file extensions to index (default: `.java`) +- `excludes` — glob patterns for source files to skip, matched against each file's path relative to + the base dir with `/` separators, e.g. `**/package-info.java`, `**/generated/**` (default: none). + `*` stays within one path segment, `**` spans directories, `?` is a single character. - `generationProvider` — AI backend: `mock` (default) or `llamacpp-jni` - `force` — regenerate even when a body already exists (default: `false`) -- `skip` — skip the goal entirely (default: `false`) +- `skip` — global switch: skip **every** phase (default: `false`) +- Per-phase switches — turn any of the three phases on/off independently (each default `false`). + Named after the three index levels (`file` / `package` / `project`, the `x` node types): + - `aiIndex.file.skip` — skip the **file** phase (the `generate` goal) + - `aiIndex.package.skip` — skip the **package** phase (the `aggregate-packages` goal) + - `aiIndex.project.skip` — skip the **project** phase (the `aggregate-project` goal) + + So `-DaiIndex.package.skip=true` runs file + project only, `-DaiIndex.skip=true` runs + nothing, and the defaults run all three. - `aiDefinitions` / `promptDefinitions` — named models / prompt templates, referenced by key - `fieldGenerations` — per goal: which `promptKey` runs with which `aiDefinitionKey` (**required**) @@ -247,9 +319,19 @@ Per-model parameters — model path, context size, output tokens, temperature, t repeat penalty, threads — live inside each ``, not as top-level parameters. ## Prompt System Prompts are defined in the plugin configuration (``) and referenced by key -from ``. The self-test profile defines two: -- `file-body` — summarizes a single source file +from ``. The self-test profile defines five: +- `file-body-java` — summarizes a single Java source file (types, public API, dependencies) +- `file-body-sql` — summarizes a single SQL file as schema (tables/views/procedures, columns, + the tables it reads vs writes, and relationships) +- `file-body-fallback` — generic multi-language summary for any other source file - `package-body` — synthesizes a package summary from the already-generated file summaries +- `project-body` — (optional) synthesizes the short project `#### Overview` paragraph from the package leads + +For the `generate` goal the file-level prompt is selected per file by extension: the first field +generation whose `` matches the file name wins; otherwise the first entry without a +`` filter is the fallback. A single field generation with no filter (the historical +shape) keeps working — it is simply the fallback for every file. + Each summary begins with a one-sentence blockquote lead, followed by structured `####` sections. Prompts are optimized to avoid code blocks, formatter artifacts, and empty outputs, and to produce structured markdown. ## Output Structure diff --git a/TODO.md b/TODO.md index 7bab3cc..6f3fdb0 100644 --- a/TODO.md +++ b/TODO.md @@ -15,7 +15,7 @@ cross-cutting initiative. - **SpotBugs `effort=Max` + `threshold=Low`** — ✅ **enforced at the gate** (`0bddf2a`). `pom.xml` `Max` + `Low`; `spotbugs:check` is part of `mvn verify` and fails on any unsuppressed finding. The full clearing chain is recorded in [`../workspace/crossrepostatus.md`](../workspace/crossrepostatus.md) under "SpotBugs Max+Low". `spotbugs-exclude.xml` carries narrow `` blocks with rationale: Lombok-USBR, HelpMojo auto-gen family, Maven `@Parameter` SPP, identity-IMC, prompt-template `FORMAT_STRING`, fb-contrib flow-coarseness sites, NPE→`MojoExecutionException` bridge. -- **Mutation-testing threshold enforcement (PIT)** — `pom.xml` wires `100`. **Scope expanded 2026-06-07** from the single `AiCompletionParser` target to an explicit **19-class** list (config / document / prompt / provider / support value + support classes; 138 mutations, all killed). Still open (optional): `document.AiMdDocumentCodec` / `AiMdHeaderCodec` / `prompt.AiPromptPreparationSupport` (need careful codec fixtures). `support.AiPathSupport` and `provider.AiGenerationProviderFactory` are excluded — equivalent / native-dependent mutants (see crossrepostatus "Deliberate non-parity"). +- **Mutation-testing threshold enforcement (PIT)** — `pom.xml` wires `100`. The explicit `` list now covers **24 classes** (config / document / prompt / provider / support value + support classes; **200 mutations, all killed**). Latest additions landed with the three-level index work: `document.AiMdLeadExtractor` (project index), `config.AiFieldGenerationSelector` (extension-based prompt selection), and `support.AiSourceExcludeFilter` (exclude globs). Still open (optional): `document.AiMdDocumentCodec` / `AiMdHeaderCodec` / `prompt.AiPromptPreparationSupport` (need careful codec fixtures). The orchestration layers (`indexer.*`, `mojo.*`) and the JNI provider stay out of PIT — they need a Maven/native context rather than pure-unit mutation (see crossrepostatus "Deliberate non-parity"). - **Additional ArchUnit rules to consider** — the full **`layeredArchitecture()`** rule and **per-module banned-imports** (`jniConfinedToProvider`, `mavenMojoAnnotationsConfinedToMojo`, `foundationIsMavenFree`) are now DONE (see "Done" below). No further ArchUnit rules outstanding. @@ -25,6 +25,35 @@ cross-cutting initiative. ## Done (kept for history) +### Three-level hierarchical index + per-phase switches + +The project index (third level) and its surrounding navigation / prompt / scaling work: + +- **Project index (`aggregate-project` goal / `ProjectIndexer`)** — harvests the one-line blockquote + lead of every `package.ai.md` (`AiMdLeadExtractor`) into a single, always-loadable `project.ai.md` + table of contents. Deterministic listing, no model. Node type `x: project`, `PROJECT_AI_MD_FILENAME`. +- **Header `F` child-link navigation (level 2 → 1)** — `AiMdHeader` carries a repeatable `F` markdown + link list (children for a package, packages for the project), so navigation stays in the + machine-parseable header while the body stays free-form. `AiMdDocumentCodec` parses only the header + block, so a `- F:` line in the body is never read as a link. +- **Language-specific file prompts** — `AiFieldGenerationConfig` gained `fileExtensions`; + `AiFieldGenerationSelector` picks the per-file prompt by extension (`.java` / `.sql` / fallback) while + one model stays loaded. Backward compatible: a single extension-less entry is the universal fallback. +- **Exclude globs** — `AiSourceExcludeFilter` (a pure, cross-platform glob matcher: `*` within a + segment, `**` across, `?` one char) + the `excludes` parameter (`aiIndex.excludes`) skip + trivial/generated sources during the file walk. +- **Optional AI project overview** — opt-in `#### Overview` paragraph synthesised from the package + leads (never the full bodies), gated incrementally by folding the generation signature + (`promptKey:aiDefinitionKey`) — not the AI output — into the `c` checksum, so an unchanged project is + never re-inferred but enabling/switching the overview, or a package change, rebuilds it. +- **Independently switchable phases** — `AbstractAiIndexMojo` owns the global `skip` (`aiIndex.skip`), + the abstract `isPhaseSkipped()` seam and `shouldSkip() = skip || isPhaseSkipped()`; each goal adds one + `skip` `@Parameter` named after the index level (`aiIndex.file.skip` / `aiIndex.package.skip` / + `aiIndex.project.skip`). Covered by `MojoPhaseSkipTest`. + +Gates: 174 tests green (1 JNI integration test skipped without the native lib); SpotBugs `Max`+`Low` +clean; full PIT 200/200 (100%); javadoc clean. + ### Layered package restructure (flat plugin package → layered hierarchy) The 34 classes that sat flat in `net.ladenthin.maven.llamacpp.aiindex` were split diff --git a/pom.xml b/pom.xml index 54f8476..58dd748 100644 --- a/pom.xml +++ b/pom.xml @@ -673,6 +673,7 @@ SPDX-License-Identifier: Apache-2.0 net.ladenthin.maven.llamacpp.aiindex.config.AiFieldGenerationConfig + net.ladenthin.maven.llamacpp.aiindex.config.AiFieldGenerationSelector net.ladenthin.maven.llamacpp.aiindex.config.AiGenerationConfig net.ladenthin.maven.llamacpp.aiindex.config.AiModelDefinition net.ladenthin.maven.llamacpp.aiindex.config.AiModelDefinitionSupport @@ -682,6 +683,7 @@ SPDX-License-Identifier: Apache-2.0 net.ladenthin.maven.llamacpp.aiindex.document.AiMdDocument net.ladenthin.maven.llamacpp.aiindex.document.AiMdHeader net.ladenthin.maven.llamacpp.aiindex.document.AiMdHeaderSupport + net.ladenthin.maven.llamacpp.aiindex.document.AiMdLeadExtractor net.ladenthin.maven.llamacpp.aiindex.prompt.AiPreparedPrompt net.ladenthin.maven.llamacpp.aiindex.prompt.AiPromptDefinition net.ladenthin.maven.llamacpp.aiindex.prompt.AiPromptSupport @@ -691,6 +693,7 @@ SPDX-License-Identifier: Apache-2.0 net.ladenthin.maven.llamacpp.aiindex.provider.MockAiGenerationProvider net.ladenthin.maven.llamacpp.aiindex.support.AiChecksumSupport net.ladenthin.maven.llamacpp.aiindex.support.AiPathSupport + net.ladenthin.maven.llamacpp.aiindex.support.AiSourceExcludeFilter net.ladenthin.maven.llamacpp.aiindex.support.AiTimeSupport net.ladenthin.maven.llamacpp.aiindex.support.Java8CompatibilityHelper @@ -1215,13 +1218,116 @@ SPDX-License-Identifier: Apache-2.0 --> - file-body + file-body-java + + + + file-body-sql + + + + file-body-fallback + + + project-body + @@ -1321,9 +1441,34 @@ File summaries: generate + + + .java + .sql + - file-body + file-body-java + Qwen3-Coder-30B-A3B-Instruct-UD-Q4_K_XL-C64k + + .java + + + + file-body-sql + Qwen3-Coder-30B-A3B-Instruct-UD-Q4_K_XL-C64k + + .sql + + + + file-body-fallback Qwen3-Coder-30B-A3B-Instruct-UD-Q4_K_XL-C64k @@ -1345,6 +1490,32 @@ File summaries: + + + + ai-aggregate-project + prepare-package + + aggregate-project + + + + + project-body + Qwen3-Coder-30B-A3B-Instruct-UD-Q4_K_XL-C64k + + + + diff --git a/spotbugs-exclude.xml b/spotbugs-exclude.xml index a37fd20..baedd30 100644 --- a/spotbugs-exclude.xml +++ b/spotbugs-exclude.xml @@ -51,11 +51,12 @@ SPDX-License-Identifier: Apache-2.0 + + + + +