ragx-cli 0.10.0__tar.gz → 0.11.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/CHANGELOG.md +12 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/CLAUDE.md +4 -4
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/PKG-INFO +2 -2
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/README.md +1 -1
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/pyproject.toml +1 -1
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/discovery.py +35 -8
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_discovery.py +52 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.agents/skills/zvec/SKILL.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.agents/skills/zvec/api-cheatsheet.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.agents/skills/zvec/collection-management/python.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.agents/skills/zvec/collection-management/typescript.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.agents/skills/zvec/configuration.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.agents/skills/zvec/data-model.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.agents/skills/zvec/data-operations/python.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.agents/skills/zvec/data-operations/typescript.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.agents/skills/zvec/embedding.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.agents/skills/zvec/hybrid-search/python.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.agents/skills/zvec/hybrid-search/typescript.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.agents/skills/zvec/multimodal-search/python.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.agents/skills/zvec/multimodal-search/typescript.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.agents/skills/zvec/quick-start/python.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.agents/skills/zvec/quick-start/typescript.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.agents/skills/zvec/rag-system/python.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.agents/skills/zvec/rag-system/typescript.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.agents/skills/zvec/reranker.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.agents/skills/zvec/troubleshooting.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.agents/skills/zvec/vector-search/python.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.agents/skills/zvec/vector-search/typescript.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.github/workflows/publish.yml +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/.gitignore +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/AGENTS.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/CONTRACTS-PHASE23.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/CONTRACTS.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/LICENSE +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/docs/feature-temporal-weighting.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/docs/proposal-models-command-interactive-flow.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/ragx-cli-plan.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/research/bge-m3-colbert-multi-vector-late-interaction-for-ragx-rerank-alternative-and-token-level-graph-edges.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/research/bge-m3-dense-embeddings-as-ragx-provider-multilingual-quality-and-threshold-calibration.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/research/bge-m3-dense-q8-vs-nomic-q4-benchmark-2026-07-12-worktree-eval-results.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/research/bge-m3-sparse-lexical-weights-hybrid-retrieval-leg-for-ragx-vs-sqlite-fts5-bm25.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/research/bge-m3-subchunk-edge-ablation-2026-07-13-ties-again-and-beta-zero-shortlist-mechanism.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/research/fine-grained-sub-chunk-edges-with-coarse-chunk-nodes-multi-granularity-graph-rag-literature-validation.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/research/lm-studio-model-download-api-and-curated-embedding-reranker-catalog-for-ragx-models-command.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/research/subchunk-edge-ablation-2026-07-12-two-round-experiment-protocol-results-and-verdict.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/research/subchunk-size-sweep-2026-10-21-default-edge-source-subchunk-size-choice.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/skills/ragx-cli/SKILL.md +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/skills-lock.json +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/__init__.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/cli/__init__.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/cli/app.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/cli/detect.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/cli/doctor_cmd.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/cli/eval_cmd.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/cli/init_prompt.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/cli/inspect_cmd.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/cli/models_cmd.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/cli/models_ui.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/cli/output.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/cli/pipeline.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/cli/web_cmd.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/__init__.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/catalog.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/chunking.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/communities.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/config.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/context.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/corpus_globs.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/doctor.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/errors.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/eval.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/expansion.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/fusion.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/graph.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/graph_export.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/grouping.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/indexer.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/lmstudio.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/models.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/query.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/reedge.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/scoring.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/store.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/traversal.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/core/vectors.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/providers/__init__.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/providers/base.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/providers/llama_embedder.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/providers/llama_process.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/providers/llama_server.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/providers/lmstudio_process.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/providers/openai_compat.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/providers/registry.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/providers/st_reranker.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/web/__init__.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/web/handlers.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/web/query_runner.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/web/server.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/web/static/index.html +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/web/static/js/colors.js +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/web/static/js/graph.js +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/web/static/js/layout.js +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/web/static/js/main.js +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/web/static/js/query.js +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/web/static/js/render.js +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/web/static/js/util.js +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/web/static/styles.css +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/web/static/vendor/LICENSE-graphology-library.txt +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/web/static/vendor/LICENSE-graphology.txt +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/web/static/vendor/LICENSE-sigma.txt +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/web/static/vendor/graphology-library.min.js +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/web/static/vendor/graphology.umd.min.js +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/web/static/vendor/sigma.min.js +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/web/static_files.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/__init__.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/conftest.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_chunking.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_cli.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_communities.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_config_rc.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_context.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_doctor.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_eval.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_expansion.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_fusion.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_graph.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_graph_export.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_grouping.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_inspect.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_integration.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_llama_server.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_lmstudio_autostart.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_models.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_providers.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_query_cmd.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_reedge.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_store.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_traversal.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_vectors.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_web_cmd.py +0 -0
- {ragx_cli-0.10.0 → ragx_cli-0.11.0}/tests/test_web_server.py +0 -0
|
@@ -4,6 +4,18 @@ All notable changes to `ragx-cli` are documented here. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow
|
|
5
5
|
[Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [0.11.0] — 2026-10-28
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Discovery now honors every `.gitignore` in the corpus tree, not only the root one. Git
|
|
12
|
+
precedence applies: the deepest `.gitignore` with a matching pattern decides, so a subdirectory
|
|
13
|
+
can re-include (`!pattern`) what the root ignores; anchored patterns (`/foo.md`) resolve
|
|
14
|
+
relative to the directory holding the `.gitignore`; ignored directories are pruned, so a
|
|
15
|
+
negation can't re-include a file under them. Patterns are parsed with
|
|
16
|
+
`pathspec.GitIgnoreSpec`. An incremental `ragx-cli index` drops already-indexed files that a
|
|
17
|
+
nested `.gitignore` now excludes.
|
|
18
|
+
|
|
7
19
|
## [0.10.0] — 2026-10-21
|
|
8
20
|
|
|
9
21
|
### Added
|
|
@@ -55,7 +55,7 @@ src/ragx/
|
|
|
55
55
|
models.py # Chunk, ChunkDraft, FileRecord, Edge, ScoredChunk, QueryOutput
|
|
56
56
|
store.py # SQLite: files/chunks/edges/meta; replace_edges normalizes src<dst
|
|
57
57
|
vectors.py # hnswlib wrapper; soft-delete via JSON sidecar; get_vectors for graph
|
|
58
|
-
discovery.py # file walk,
|
|
58
|
+
discovery.py # file walk, nested .gitignore (git precedence), binary/size/junk-dir filters, xxh64
|
|
59
59
|
chunking.py # markdown/code/recursive splitters; byte-exact slices; tiny-fragment merge;
|
|
60
60
|
# subchunk_texts (sentence-aligned windows for subchunk edge mode)
|
|
61
61
|
graph.py # knn_edges + subchunk_knn_edges (max over sub-chunk pairs, near-dup guard)
|
|
@@ -90,13 +90,13 @@ src/ragx/
|
|
|
90
90
|
# handlers.py (routing), query_runner.py (lazy providers, lock-serialized
|
|
91
91
|
# queries), static_files.py (path-traversal-safe static serving);
|
|
92
92
|
# static/ (frontend-owned: index.html, JS/CSS, vendored sigma.js)
|
|
93
|
-
tests/ #
|
|
93
|
+
tests/ # 305 tests; mocked HTTP (respx), FakeEmbedder integration tests, no live network
|
|
94
94
|
```
|
|
95
95
|
|
|
96
96
|
## Flows
|
|
97
97
|
|
|
98
98
|
**Index** (`ragx-cli index`): discover files (include/exclude globs — defaults in
|
|
99
|
-
`core/corpus_globs.py`: source + text docs, minus lockfiles/requirements/build output —
|
|
99
|
+
`core/corpus_globs.py`: source + text docs, minus lockfiles/requirements/build output — every .gitignore in the tree (deeper overrides shallower, ignored dirs pruned),
|
|
100
100
|
skip node_modules/.venv/hidden/binaries/>2MB) → xxhash diff (incremental by default since 0.8.0;
|
|
101
101
|
`--full` rebuilds everything; `--changed` is a deprecated no-op alias for the default) → chunk
|
|
102
102
|
(~800 tok target, chunks are exact byte slices, sub-100-char fragments
|
|
@@ -205,7 +205,7 @@ mostly on Dutch/multilingual queries. Details: `research/bge-m3-dense-q8-vs-nomi
|
|
|
205
205
|
|
|
206
206
|
## Dev loop
|
|
207
207
|
|
|
208
|
-
`uv sync --group dev --extra rerank` · `uv run pytest -q` (
|
|
208
|
+
`uv sync --group dev --extra rerank` · `uv run pytest -q` (304 pass + 1 skipped, ~13 s) ·
|
|
209
209
|
`uv run ruff check src tests` · file soft cap ~150 lines · expected failures raise `RagxError`
|
|
210
210
|
(CLI maps to exit 2). Live smoke: LM Studio must be running with the configured embedding model.
|
|
211
211
|
Changes that impact usage (CLI flags, config keys/precedence, output schemas, install steps)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: ragx-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.11.0
|
|
4
4
|
Summary: Similarity-graph RAG CLI: index a corpus into a chunk-level embedding graph and query it
|
|
5
5
|
Project-URL: Repository, https://github.com/alber70g/ragx-cli
|
|
6
6
|
Project-URL: Issues, https://github.com/alber70g/ragx-cli/issues
|
|
@@ -706,7 +706,7 @@ Key defaults:
|
|
|
706
706
|
|
|
707
707
|
| section | defaults |
|
|
708
708
|
|---|---|
|
|
709
|
-
| `[corpus]` | `include` = source code (`*.py`, `*.ts`, `*.go`, `*.rs`, … ~70 extensions, plus `Dockerfile`/`Makefile`) and text docs (`*.md`, `*.mdx`, `*.rst`, `*.txt`, `*.adoc`, `*.org`); `exclude` = lockfiles (`*.lock`, `package-lock.json`, `pnpm-lock.yaml`, `go.sum`, …), `requirements*.txt`/`constraints*.txt`, `LICENSE*`/`COPYING*`, `*.min.js`/`*.min.css`/`*.map`, and `dist/`, `build/`, `target/`, `coverage/`, `vendor/`; `respect_gitignore=true`. Full lists: `src/ragx/core/corpus_globs.py`. Existing `ragx.toml` files keep their own lists |
|
|
709
|
+
| `[corpus]` | `include` = source code (`*.py`, `*.ts`, `*.go`, `*.rs`, … ~70 extensions, plus `Dockerfile`/`Makefile`) and text docs (`*.md`, `*.mdx`, `*.rst`, `*.txt`, `*.adoc`, `*.org`); `exclude` = lockfiles (`*.lock`, `package-lock.json`, `pnpm-lock.yaml`, `go.sum`, …), `requirements*.txt`/`constraints*.txt`, `LICENSE*`/`COPYING*`, `*.min.js`/`*.min.css`/`*.map`, and `dist/`, `build/`, `target/`, `coverage/`, `vendor/`; `respect_gitignore=true` (every `.gitignore` in the tree applies to its own subtree, with git precedence: deeper files override shallower ones, ignored directories are skipped whole). Full lists: `src/ragx/core/corpus_globs.py`. Existing `ragx.toml` files keep their own lists |
|
|
710
710
|
| `[chunking]` | `size_tokens=800`, `overlap=0.15` |
|
|
711
711
|
| `[graph]` | `k=8`, `min_edge_sim=0.55`, `edge_source="subchunk"`, `subchunk_size_tokens=256`, `near_dup_sim=0.9` |
|
|
712
712
|
| `[traversal]` | `hops=2`, `decay=0.5`, `query_floor=0.35`, `max_frontier=150` |
|
|
@@ -678,7 +678,7 @@ Key defaults:
|
|
|
678
678
|
|
|
679
679
|
| section | defaults |
|
|
680
680
|
|---|---|
|
|
681
|
-
| `[corpus]` | `include` = source code (`*.py`, `*.ts`, `*.go`, `*.rs`, … ~70 extensions, plus `Dockerfile`/`Makefile`) and text docs (`*.md`, `*.mdx`, `*.rst`, `*.txt`, `*.adoc`, `*.org`); `exclude` = lockfiles (`*.lock`, `package-lock.json`, `pnpm-lock.yaml`, `go.sum`, …), `requirements*.txt`/`constraints*.txt`, `LICENSE*`/`COPYING*`, `*.min.js`/`*.min.css`/`*.map`, and `dist/`, `build/`, `target/`, `coverage/`, `vendor/`; `respect_gitignore=true`. Full lists: `src/ragx/core/corpus_globs.py`. Existing `ragx.toml` files keep their own lists |
|
|
681
|
+
| `[corpus]` | `include` = source code (`*.py`, `*.ts`, `*.go`, `*.rs`, … ~70 extensions, plus `Dockerfile`/`Makefile`) and text docs (`*.md`, `*.mdx`, `*.rst`, `*.txt`, `*.adoc`, `*.org`); `exclude` = lockfiles (`*.lock`, `package-lock.json`, `pnpm-lock.yaml`, `go.sum`, …), `requirements*.txt`/`constraints*.txt`, `LICENSE*`/`COPYING*`, `*.min.js`/`*.min.css`/`*.map`, and `dist/`, `build/`, `target/`, `coverage/`, `vendor/`; `respect_gitignore=true` (every `.gitignore` in the tree applies to its own subtree, with git precedence: deeper files override shallower ones, ignored directories are skipped whole). Full lists: `src/ragx/core/corpus_globs.py`. Existing `ragx.toml` files keep their own lists |
|
|
682
682
|
| `[chunking]` | `size_tokens=800`, `overlap=0.15` |
|
|
683
683
|
| `[graph]` | `k=8`, `min_edge_sim=0.55`, `edge_source="subchunk"`, `subchunk_size_tokens=256`, `near_dup_sim=0.9` |
|
|
684
684
|
| `[traversal]` | `hops=2`, `decay=0.5`, `query_floor=0.35`, `max_frontier=150` |
|
|
@@ -20,12 +20,29 @@ def _is_binary(path: Path) -> bool:
|
|
|
20
20
|
return b"\x00" in chunk
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
def _load_gitignore_spec(
|
|
24
|
-
gitignore =
|
|
23
|
+
def _load_gitignore_spec(directory: Path) -> pathspec.GitIgnoreSpec | None:
|
|
24
|
+
gitignore = directory / ".gitignore"
|
|
25
25
|
if not gitignore.is_file():
|
|
26
26
|
return None
|
|
27
27
|
lines = gitignore.read_text(encoding="utf-8", errors="ignore").splitlines()
|
|
28
|
-
return pathspec.
|
|
28
|
+
return pathspec.GitIgnoreSpec.from_lines(lines)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _is_gitignored(rel: str, specs: dict[str, pathspec.GitIgnoreSpec]) -> bool:
|
|
32
|
+
"""Git precedence: the deepest .gitignore with a matching pattern decides.
|
|
33
|
+
|
|
34
|
+
`specs` maps a directory's root-relative POSIX path ("" = root) to its .gitignore.
|
|
35
|
+
Directory paths carry a trailing "/" so dir-only patterns (`build/`) match them.
|
|
36
|
+
"""
|
|
37
|
+
parts = rel.rstrip("/").split("/")
|
|
38
|
+
for depth in range(len(parts) - 1, -1, -1):
|
|
39
|
+
spec = specs.get("/".join(parts[:depth]))
|
|
40
|
+
if spec is None:
|
|
41
|
+
continue
|
|
42
|
+
verdict = spec.check_file("/".join(parts[depth:]) + ("/" if rel.endswith("/") else ""))
|
|
43
|
+
if verdict.include is not None:
|
|
44
|
+
return verdict.include
|
|
45
|
+
return False
|
|
29
46
|
|
|
30
47
|
|
|
31
48
|
def discover_files(
|
|
@@ -37,17 +54,27 @@ def discover_files(
|
|
|
37
54
|
"""Return sorted relative POSIX paths of files matching include/exclude under root.
|
|
38
55
|
|
|
39
56
|
Always skips ALWAYS_SKIP_DIRS, hidden directories, the corpus's own root-level
|
|
40
|
-
ragx.toml, binaries (NUL byte in first 8KB), and files larger than 2MB.
|
|
41
|
-
|
|
57
|
+
ragx.toml, binaries (NUL byte in first 8KB), and files larger than 2MB. With
|
|
58
|
+
respect_gitignore, every .gitignore in the tree applies to its own subtree (git
|
|
59
|
+
semantics: deeper files override shallower ones; ignored directories are pruned,
|
|
60
|
+
so a negation can't re-include a file under them).
|
|
42
61
|
"""
|
|
43
62
|
include_spec = pathspec.PathSpec.from_lines("gitwildmatch", include)
|
|
44
63
|
exclude_spec = pathspec.PathSpec.from_lines("gitwildmatch", exclude) if exclude else None
|
|
45
|
-
|
|
64
|
+
gitignore_specs: dict[str, pathspec.GitIgnoreSpec] = {}
|
|
46
65
|
|
|
47
66
|
results: list[str] = []
|
|
48
67
|
for dirpath, dirnames, filenames in root.walk():
|
|
68
|
+
dir_rel = dirpath.relative_to(root).as_posix()
|
|
69
|
+
dir_rel = "" if dir_rel == "." else dir_rel
|
|
70
|
+
if respect_gitignore and (spec := _load_gitignore_spec(dirpath)) is not None:
|
|
71
|
+
gitignore_specs[dir_rel] = spec
|
|
49
72
|
dirnames[:] = [
|
|
50
|
-
d
|
|
73
|
+
d
|
|
74
|
+
for d in dirnames
|
|
75
|
+
if d not in ALWAYS_SKIP_DIRS
|
|
76
|
+
and not d.startswith(".")
|
|
77
|
+
and not _is_gitignored(f"{dir_rel}/{d}/".lstrip("/"), gitignore_specs)
|
|
51
78
|
]
|
|
52
79
|
for name in filenames:
|
|
53
80
|
path = dirpath / name
|
|
@@ -59,7 +86,7 @@ def discover_files(
|
|
|
59
86
|
continue
|
|
60
87
|
if exclude_spec is not None and exclude_spec.match_file(rel):
|
|
61
88
|
continue
|
|
62
|
-
if
|
|
89
|
+
if _is_gitignored(rel, gitignore_specs):
|
|
63
90
|
continue
|
|
64
91
|
|
|
65
92
|
try:
|
|
@@ -101,6 +101,58 @@ def test_discover_respects_root_gitignore(tmp_path: Path):
|
|
|
101
101
|
assert files == [".gitignore", "kept.txt"]
|
|
102
102
|
|
|
103
103
|
|
|
104
|
+
def test_discover_respects_nested_gitignore_scoped_to_its_subtree(tmp_path: Path):
|
|
105
|
+
# A subproject's .gitignore (e.g. a vendored repo's generated docs) must keep its
|
|
106
|
+
# junk out of the index, but must not leak onto same-named files elsewhere.
|
|
107
|
+
_write(tmp_path, "sub/.gitignore", "generated.md\n/anchored.md\n")
|
|
108
|
+
_write(tmp_path, "sub/generated.md")
|
|
109
|
+
_write(tmp_path, "sub/deep/generated.md")
|
|
110
|
+
_write(tmp_path, "sub/anchored.md")
|
|
111
|
+
_write(tmp_path, "sub/deep/anchored.md")
|
|
112
|
+
_write(tmp_path, "generated.md")
|
|
113
|
+
_write(tmp_path, "anchored.md")
|
|
114
|
+
|
|
115
|
+
files = discover_files(tmp_path, include=["**/*.md"], exclude=[], respect_gitignore=True)
|
|
116
|
+
|
|
117
|
+
# "/anchored.md" anchors to sub/, so only sub/anchored.md is dropped.
|
|
118
|
+
assert files == ["anchored.md", "generated.md", "sub/deep/anchored.md"]
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def test_discover_deeper_gitignore_overrides_root(tmp_path: Path):
|
|
122
|
+
# Git precedence: the deeper file wins, so a subdir can re-include what root ignores.
|
|
123
|
+
_write(tmp_path, ".gitignore", "*.log.md\n")
|
|
124
|
+
_write(tmp_path, "notes/.gitignore", "!keep.log.md\n")
|
|
125
|
+
_write(tmp_path, "notes/keep.log.md")
|
|
126
|
+
_write(tmp_path, "notes/drop.log.md")
|
|
127
|
+
_write(tmp_path, "keep.log.md")
|
|
128
|
+
|
|
129
|
+
files = discover_files(tmp_path, include=["**/*.md"], exclude=[], respect_gitignore=True)
|
|
130
|
+
|
|
131
|
+
assert files == ["notes/keep.log.md"]
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def test_discover_prunes_gitignored_directories(tmp_path: Path):
|
|
135
|
+
# Git can't re-include a file whose parent dir is ignored; ragx must not index it
|
|
136
|
+
# either, or the index would contain files git itself never tracks.
|
|
137
|
+
_write(tmp_path, ".gitignore", "out/\n")
|
|
138
|
+
_write(tmp_path, "pkg/out/.gitignore", "!kept.md\n")
|
|
139
|
+
_write(tmp_path, "pkg/out/kept.md")
|
|
140
|
+
_write(tmp_path, "pkg/src.md")
|
|
141
|
+
|
|
142
|
+
files = discover_files(tmp_path, include=["**/*.md"], exclude=[], respect_gitignore=True)
|
|
143
|
+
|
|
144
|
+
assert files == ["pkg/src.md"]
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def test_discover_ignores_nested_gitignore_when_disabled(tmp_path: Path):
|
|
148
|
+
_write(tmp_path, "sub/.gitignore", "hidden.md\n")
|
|
149
|
+
_write(tmp_path, "sub/hidden.md")
|
|
150
|
+
|
|
151
|
+
files = discover_files(tmp_path, include=["**/*.md"], exclude=[], respect_gitignore=False)
|
|
152
|
+
|
|
153
|
+
assert files == ["sub/hidden.md"]
|
|
154
|
+
|
|
155
|
+
|
|
104
156
|
def test_discover_ignores_gitignore_when_disabled(tmp_path: Path):
|
|
105
157
|
_write(tmp_path, ".gitignore", "notignored.txt\n")
|
|
106
158
|
_write(tmp_path, "notignored.txt")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ragx_cli-0.10.0 → ragx_cli-0.11.0}/src/ragx/web/static/vendor/LICENSE-graphology-library.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|