Repository navigation
feat(autoindex): budget the index before hashing - #2102
Conversation
main serves eighteen tools now and xerj-org#2102 adds a nineteenth; the tested row is about the client registering the server, not the count.
* docs(readme): list 26 supported agent harnesses (#1991) Motivation: xerj init writes configs for three clients and prints setup lines for three more, while comparable tools publish a table of 20 or more, and readers use that list to decide whether a tool fits their setup. The gap is documentation, not code. What changed: a Supported agents section in the README, one row per client with its config file, config key, a note and a tested mark, the non-JSON shapes as snippets, and the same 26-row list on the docs CLI page. Verification: xerj v1.0.0-rc.97 on Windows answered initialize and tools/list over stdio, and OpenCode 2.1.2 registered the binary and reported connected after opencode mcp add wrote the project config. The other 25 rows are transcribed from each client's own documentation and are marked untested. Aider, T3 Code and Grok Bot are listed as excluded, with the reason. Signed-off-by: kclamano <klamano23@gmail.com> * docs: don't pin the MCP tool count in the supported-agents text main serves eighteen tools now and #2102 adds a nineteenth; the tested row is about the client registering the server, not the count. --------- Signed-off-by: kclamano <klamano23@gmail.com> Co-authored-by: Xerj Merger <merger@xerj.org>
autoindex hashed the folder before anyone could see whether the index would fit. A digit-leading prefix was rejected only after that hash (#2057), exit 3 did not name the skipped files (#2056), and the same folder under a second prefix was silent (#2078). The free-disk budget reuses the one pre-walk GET /_cat/allocation from the flood-stage probe. It does not issue a second allocation request. Already-over-flood still stops before the walk. Under the watermark the budget is free bytes above the reported flood reserve; the threshold is not guessed when the node omits it. --max-index-size can lower that budget. Per-kind ratios are dataset-index store sizes measured 2026-10-21 with xerj v1.0.0-rc.97 (default lexical feature-hash; the neural embedder was not enabled). A kind with no row stays unmeasured and does not refuse the run. When the default plan does not fit, stdout is a JSON plan list and the process exits 4 until --plan or --yes names a plan that fits. MCP xerj_index_budget returns the same estimate and does not index. Corpus index still drops CSV/HDF/simulation files before the estimate when skip_corpus_data is set. The budget then sees the files that will actually be hashed. Verified after rebasing onto origin/main (which already has #2086 and - test -p xerj-autoindex --lib -- --test-threads=8: 1545 passed, 0 failed, 2 ignored, finished in 34.26s - test -p xerj-mcp: lib 102 passed; published schema drift 4 passed; hub_tools 1 passed; search_exact_phrase 1 passed - test -p xerj-api --test flood_stage_allocation: 1 passed - clippy -p xerj-autoindex -p xerj-mcp -p xerj-console-api --all-targets -- -D warnings: exit 0 - check -p xerj-autoindex -p xerj-mcp -p xerj-server -p xerj-console-api: exit 0 - fmt -p xerj-autoindex -p xerj-mcp -p xerj-server -p xerj-console-api Not run: ES-YAML. This commit does not change the engine wire. The allocation JSON lives in the parent commit, which is the unmerged flood-stage probe (#2087). A release rebuild of this tree. Workspace-wide cargo test. xerj-console-api tests. cargo fmt --all.
The synthetic distinct-token trees under-predicted real .rs and .md indices by about 3.5x (97 files / 5.1 MB of code: model 4.3 MB, measured 15.3 MB). Replace the code and prose points with real-content runs on rc.97; data, pdf and unindexed points stay synthetic.
… wrong Naming a plan with --plan (or typing it at the prompt) now runs it even when the estimate says it does not 8000 fit, with a warning in the continue note. The estimate errs high after the real-content calibration, and the flood-stage guard still stops writes. The implicit default and --yes keep their behaviour. Also fixes the stray ' . ' in the default-plan line.
…lder The same-folder-under-another-prefix note (#2078) suggested "DELETE /<other>-* to drop the other copy". A prefix can hold other folders (the unit test's own fixture has ax indexing /data/proj and /data/old), and the node accepts that wildcard delete, so following the hint destroys indices this run never touched. That is the failure in the #2114 field report. The note now names --prefix <other> and says both copies are kept.
300cc12 to
dcdcd5b
Compare
|
Thank you for your pull request and welcome to our community. We could not parse the GitHub identity of the following contributors: Xerj Merger.
|
|
Xerj Merger made the fix: I rebased onto main ( Rebase conflict (lib.rs). #2087 now lets b9a64d0: recalibrated code and prose on real content. The MEASURED code and prose points came from small synthetic distinct-token trees, and they under-predict real repositories by about 3.5x. Measured with rc.97 on copies of this repository:
The new points are 5/97 38a573a: a named dcdcd5b: removed a destructive hint. The new same-folder-under-another-prefix note (#2078) told agents to Other review points, unchanged:
Local CI:
The PR touches no workflow files. Squash-merging. |
#2102 added xerj_index_budget, so main serves nineteen MCP tools (sixteen with no hub key). llms.txt and llms-full.txt said eighteen/fifteen and README/cli.html said seventeen/fourteen. Name the tool and fix the counts. Co-authored-by: Xerj Merger <merger@xerj.org>
What this changes, and why
xerj autoindexhashed and embedded a folder before anyone could see whether the index would fit. A digit-leading--prefixwas rejected only after that hash (#2057). Exit 3 did not name the skipped files, and a PDF reuse-fallback line did not say the PDF was still indexed (#2056). The same folder under a second prefix was silent (#2078).After the walk, and before hashing, autoindex now estimates the index from measured per-kind store-size ratios and compares that with the free space left under the node's flood-stage watermark. The budget reads the allocation row already fetched by the pre-walk probe. It does not issue a second
GET /_cat/allocation. A node that omitsdisk.flood_stagedoes not get a guessed 95% margin.--max-index-sizecan lower the budget. When the default plan does not fit, stdout is a JSON plan list and the process exits 4 until--planor--yesnames a plan that fits. An unmeasured kind does not refuse the run. MCPxerj_index_budgetreturns the same estimate and does not index.Fixes #2056. Fixes #2057. Fixes #2078.
This branch is stacked on the unmerged flood-stage probe. Commit
ce41dea5is #2087 rebased onto currentmain. The budget work is onlyce41dea5..HEAD. Do not merge this draft until #2087 is onmainand that parent commit is dropped:#2086 (stale resume plan) and #2085 (MCP node-down hint) are already on
main. This branch does not redo them. #2006 (--walk-only) was not folded in; the existing walk is the counting pass.Evidence
The estimator's ratios are dataset-index
store.sizevalues measured 2026-10-21 with/workspace/engine/target/release/xerjreportingxerj v1.0.0-rc.97, started--insecure(lexical feature-hash;--embed-mode neuralwas not passed). Host: Linux 6.12.94+ x86_64, 4 cores, 16387280 KiB RAM. Harness (not committed):python3 /tmp/calibrate_budget.py. Recorded stdout:/tmp/xerj-cal3-results.jsonl.autoindex-catalogstore size was excluded because it moved by tens of KB in both directions between runs. The two PDF points are about 1 KB and 10 KB and have a negative per-byte slope, so the fitter uses the steeper measured ratio. A kind with no row stays unmeasured.After rebasing onto
origin/main(cargo +1.97.1fromengine/,--offline,-j 4):The end-to-end test builds a tree with
main.rsand a 2000-row csv, asks for an estimate withno_semanticand an unbounded--max-index-size, caps the budget at thecode-and-docsestimate, and checks that a run with no--planreturns exit 4 with no data bulk. A second run with--plan code-and-docsreturns 0 and indexesmain.rsand notbig.csv.Checks
cargo fmt --all(CI runsrustfmt --checkandclippy -D warnings)cargo build --release -j 32 -p <crate>cargo test -p <crate>passes (cargo checkis not sufficient — test code is interleaved with production code)cargo run --release -p es-yaml-runner -- --dir tests/es-compat-yaml/yaml), or: not applicable because this change is docs/landing-onlyengine/tests/es-compat-yaml/yaml/docs/CONTRIBUTION_REVIEW.mddocs/CONTRIBUTION_REVIEW.md. Record a negative control that exits non-zero with no artifact extracted, installed, published, or served. Keep verification and its action in one block; rerun the control with the failing exit discarded and with the next documented block appended, and require that neither reaches an artifact or unsafe/privileged path. List tested variants and unsupported variants separately, and verify every publication copy. Otherwise mark this itemN/Awith a reason.Not run:
cargo fmt --all(fmt wascargo +1.97.1 fmt -p xerj-autoindex -p xerj-mcp -p xerj-server -p xerj-console-api). Scoped release build of this tree (the calibration binary was an earlier release build ofxerj v1.0.0-rc.97, not a rebuild after the final client). Workspace-widecargo test.xerj-console-apitests (clippy compiled the crate). ES-YAML. The budget commit does not change the engine wire. The allocation JSON is the parent commit, which is #2087; that commit's own message says the ES-YAML runner was not run there either, and no YAML case references/_cat/allocation. No new YAML case in this PR.landing/llms.txtandlanding/llms-full.txtwere not edited. Open PRs #1909 and #1925 already editlanding/llms.txt, and only one open PR may edit that file. The published tool count there is still short byxerj_index_budget. The generated schemalanding/docs/agents/schemas/mcp-tools.jsonwas updated, andpublished_schema_driftpassed (19 tools with hub, 16 without). CLI help andCHANGELOG.mdwere updated.Operational-recipe audit: N/A. This change adds CLI flags and help text, not a new runnable recipe, install path, or publication copy.
Contribution review
origin/main. Unique commits arece41dea5(fix(autoindex): fail fast when the node disk is at flood stage #2087, temporary) and the budget commit. fix(autoindex): a stale resume plan is not junk (#2076) #2086 and fix(mcp): say how to start a node when XERJ_URL is down #2085 are on main and were not replayed. The walk keepsskip_corpus_data(corpus index, corpus index: skip bulky data files (CSV/HDF/test output) by default for reference corpora #1985) and the budget estimates the files left after that filter.skippedis added to the run document only when junk is non-empty, and the human summary prints at most 20skipped:lines after the one-lineok:headline.--max-minutes 0still only disables the time gate. The disk budget stays on.--yeswhen the default plan does not fit accepts the recommended plan that fits. If none fit, the run still exits 4.--watch: later passes clone the original config.--planand--yespersist because they are on the config. Local--watchallows the new flags; object-storage--watchandmap/statusrefuse them, same as--max-minutes.max_index_bytesandbudget_planunset. A brain folder that does not fit exits 4.Provenance
Co-authored-bytrailer on the budget commit.engine/crates/xerj-autoindex/src/budget.rs(MEASURED), taken from the release binary and harness named there.xerj --versionon that binary printedxerj v1.0.0-rc.97.--embed-mode neural(the calibration note says they do not; a neural run was not done). That a reduced plan on an already-indexed folder surfaces as a deletion delta (read from the existing checker, not exercised). That--watchforgets a TTY plan (follows from later passes cloning the original config; no watch run was done). ES-YAML stays at 0 failed with the stacked allocation JSON (not run here).