@functional-systems/srcx 0.1.0-dev.3 → 0.1.0-dev.30

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.
Files changed (60) hide show
  1. package/CHANGELOG.md +132 -1
  2. package/DESIGN.md +193 -58
  3. package/README.md +542 -38
  4. package/RELEASING.md +30 -9
  5. package/VALIDATION.md +834 -25
  6. package/dist/build.d.ts +81 -1
  7. package/dist/build.js +187 -37
  8. package/dist/build.js.map +1 -1
  9. package/dist/chunk.d.ts +9 -3
  10. package/dist/chunk.js +341 -14
  11. package/dist/chunk.js.map +1 -1
  12. package/dist/cli.js +103 -19
  13. package/dist/cli.js.map +1 -1
  14. package/dist/file-policy.d.ts +20 -0
  15. package/dist/file-policy.js +96 -0
  16. package/dist/file-policy.js.map +1 -0
  17. package/dist/implementation.d.ts +11 -0
  18. package/dist/implementation.js +191 -0
  19. package/dist/implementation.js.map +1 -0
  20. package/dist/publish.d.ts +18 -0
  21. package/dist/publish.js +158 -34
  22. package/dist/publish.js.map +1 -1
  23. package/dist/releases.js +21 -3
  24. package/dist/releases.js.map +1 -1
  25. package/dist/remote.js +38 -9
  26. package/dist/remote.js.map +1 -1
  27. package/dist/repository.d.ts +4 -1
  28. package/dist/repository.js +15 -11
  29. package/dist/repository.js.map +1 -1
  30. package/dist/rerank.d.ts +16 -0
  31. package/dist/rerank.js +87 -0
  32. package/dist/rerank.js.map +1 -0
  33. package/dist/search.d.ts +14 -4
  34. package/dist/search.js +119 -23
  35. package/dist/search.js.map +1 -1
  36. package/dist/skills.d.ts +24 -0
  37. package/dist/skills.js +155 -0
  38. package/dist/skills.js.map +1 -0
  39. package/package.json +16 -5
  40. package/runtime/grammars/README.md +50 -0
  41. package/runtime/grammars/tree-sitter-bash.LICENSE +21 -0
  42. package/runtime/grammars/tree-sitter-bash.wasm +0 -0
  43. package/runtime/grammars/tree-sitter-sql.LICENSE +21 -0
  44. package/runtime/grammars/tree-sitter-sql.wasm +0 -0
  45. package/runtime/grammars/tree-sitter-wasm.LICENSE +21 -0
  46. package/runtime/qwen.py +132 -0
  47. package/runtime/requirements.txt +34 -0
  48. package/skills/srcx-search/SKILL.md +85 -0
  49. package/src/build.ts +258 -47
  50. package/src/chunk.ts +360 -12
  51. package/src/cli.ts +212 -24
  52. package/src/file-policy.ts +157 -0
  53. package/src/implementation.ts +253 -0
  54. package/src/publish.ts +226 -34
  55. package/src/releases.ts +36 -3
  56. package/src/remote.ts +59 -13
  57. package/src/repository.ts +20 -11
  58. package/src/rerank.ts +131 -0
  59. package/src/search.ts +154 -28
  60. package/src/skills.ts +205 -0
package/README.md CHANGED
@@ -4,14 +4,101 @@ Version-aware code search on LambdaDB. Import a committed Git tree, search its
4
4
  chunks, and read exact source pinned to a validated immutable version.
5
5
 
6
6
  This is an experimental development CLI. Local fixture, fault-injection, SDK transport,
7
- and opt-in live acceptance checks are available. The npm package is prepared for
8
- publication but remains unpublished. See [VALIDATION.md](VALIDATION.md) for the latest observed results and
7
+ and opt-in live acceptance checks are available. Development builds are available
8
+ on npm under `@functional-systems/srcx@dev`. See [VALIDATION.md](VALIDATION.md) for the latest observed results and
9
9
  remaining scope, and [DESIGN.md](DESIGN.md) for the full design.
10
10
 
11
+ ## Install a development build
12
+
13
+ Requires Node.js 22.14+ and Git. These are experimental prereleases; there is no
14
+ stable release yet. Select the `dev` channel explicitly:
15
+
16
+ ```sh
17
+ npm install -g @functional-systems/srcx@dev
18
+ srcx --version
19
+ srcx --help
20
+ ```
21
+
22
+ ## Install the agent skill
23
+
24
+ The npm package includes the [srcx-search skill](skills/srcx-search/SKILL.md).
25
+ After installing the CLI, explicitly select your agent:
26
+
27
+ ```sh
28
+ srcx skills install --agent codex
29
+ # Or, for Claude Code:
30
+ srcx skills install --agent claude
31
+ srcx skills status --agent codex
32
+ ```
33
+
34
+ The default scope is `user`. Installation copies the bundled instructions into
35
+ one of the following local discovery directories:
36
+
37
+ | Agent | User scope | Project scope |
38
+ | ----------- | --------------------------------------- | ----------------------------------------------- |
39
+ | Codex | `~/.agents/skills/srcx-search/SKILL.md` | `<project>/.agents/skills/srcx-search/SKILL.md` |
40
+ | Claude Code | `~/.claude/skills/srcx-search/SKILL.md` | `<project>/.claude/skills/srcx-search/SKILL.md` |
41
+
42
+ These are the documented local skill locations for
43
+ [Codex](https://learn.chatgpt.com/docs/build-skills#where-codex-loads-local-skills)
44
+ and [Claude Code](https://code.claude.com/docs/en/skills#where-skills-live).
45
+ Cloud sessions need their own installation; a local user installation does not
46
+ configure remote agents or account-synced skills. The installer targets these
47
+ default locations, not custom agent configuration directories.
48
+
49
+ To share a skill with a project, select an existing project directory and commit
50
+ the installed file if appropriate for your team:
51
+
52
+ ```sh
53
+ srcx skills install --agent codex --scope project --path /path/to/project
54
+ ```
55
+
56
+ Project scope defaults to the current directory when `--path` is omitted; it does
57
+ not infer the Git root. `--path` is accepted only for project scope. Prefer one
58
+ scope per agent to avoid duplicate skill names. The installer does not change
59
+ `AGENTS.md`, `CLAUDE.md`, agent permissions, shell profiles or credentials, and npm
60
+ installation alone does not place skills in your environment.
61
+
62
+ Make sure the agent's shell can run `srcx --version`. Configure LambdaDB and
63
+ prepare the repository using the [connected workflow](#connected-workflow) below,
64
+ or use an already indexed repository in the configured project. The agent process
65
+ must inherit the API-key environment variable named by `srcx configure`; no key
66
+ is copied into the skill. `srcx doctor` checks authentication/read access only.
67
+
68
+ Start a new agent session after installation. Invoke `$srcx-search` in Codex or
69
+ `/srcx-search` in Claude Code, and ask it to investigate an indexed repository at a
70
+ specific branch, release or commit. Skill-aware agents may also select it from its
71
+ description. Installation/status confirms files on disk, not that an agent loaded
72
+ or selected them. Agent policy, disabled skills and custom discovery paths can
73
+ still affect availability.
74
+
75
+ ### Update and remove
76
+
77
+ ```sh
78
+ npm install -g @functional-systems/srcx@dev
79
+ srcx skills update --agent codex
80
+ srcx skills status --agent codex
81
+ srcx skills remove --agent codex
82
+ ```
83
+
84
+ Repeat for each installed agent/scope, supplying the same `--scope project --path`
85
+ when applicable. `update` uses the currently running CLI's bundled skill and does
86
+ not download anything. npm upgrades do not silently update skill copies, and npm
87
+ uninstall does not remove them: run `skills remove` before uninstalling the CLI.
88
+
89
+ A provenance comment records the package version and content hash. Repeated
90
+ installation is a no-op when the installed copy matches. A different managed
91
+ version requires `update`. Locally edited skills, extra files, unowned skills and
92
+ symlinked managed paths are preserved by refusing the operation; there is no
93
+ force-overwrite flag. Move a customized copy to a separate skill name/location
94
+ before installing a managed copy. Interrupted operations can leave a sibling
95
+ `.srcx-search.srcx-lock` directory: check that no installer is running and preserve
96
+ any staged file before manually removing that lock and retrying.
97
+
11
98
  ## Run locally
12
99
 
13
- Requires Node.js 22.14+ and Git. The initial preset uses lexical search with
14
- `embedding=none`; no embedding account or paid API is needed.
100
+ Requires Node.js 22.14+ and Git. The default preset uses lexical search with
101
+ `embedding=none` and the `standard` text analyzer; no embedding account or paid API is needed.
15
102
 
16
103
  ```sh
17
104
  npm ci --ignore-scripts
@@ -27,11 +114,11 @@ artifacts. It does not contact LambdaDB. The model's lexical matching is a test
27
114
  convenience, not a Lucene implementation or a relevance benchmark.
28
115
 
29
116
  All commands return JSON, except help and errors. Use `node dist/cli.js` in this
30
- checkout; `srcx` is the configured executable name for future distribution.
117
+ checkout, or `srcx` after installing the npm package.
31
118
 
32
119
  For development branches, CI, and installed-package checks, see
33
120
  [CONTRIBUTING.md](CONTRIBUTING.md). Version channels, first-publication steps, and
34
- the initially disabled npm automation are documented in [RELEASING.md](RELEASING.md).
121
+ npm automation are documented in [RELEASING.md](RELEASING.md).
35
122
  The project is licensed under [Apache-2.0](LICENSE).
36
123
 
37
124
  ## Preview a committed version without credentials
@@ -55,16 +142,353 @@ Each artifact contains `build.json` (inventory, configuration, counts, hashes,
55
142
  change/deletion plan) and `records.jsonl` (exact file records and retrieval chunks).
56
143
  Artifacts contain source code; keep them with the same access policy as the repo.
57
144
  Every tree entry is accounted for, including explicit exclusions for symlinks,
58
- submodules, LFS pointers, dependencies/build output, binary/invalid UTF-8 data,
145
+ submodules, LFS pointers, dependencies/build output, image assets (including SVG), binary/invalid UTF-8 data,
59
146
  invalid UTF-8 paths, and files above 1 MiB. Excluded paths are preserved losslessly
60
147
  in `pathBase64`.
148
+ Image extensions are matched case-insensitively and excluded before chunking or
149
+ embedding, even when their payload is readable text. Source files containing
150
+ inline images, such as a TSX component with SVG markup, remain included.
151
+
152
+ File selection and embedding eligibility are separate:
153
+
154
+ | Default treatment | Examples |
155
+ | --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
156
+ | Exclude source and chunks | Credential files (`.env`, `.env.*`, `.npmrc`, `.netrc`, `.aws/`, `.ssh/`), key/certificate payloads, images, binaries, installed dependencies (`.venv/`, `node_modules/`, `vendor/`, `third_party/`), build/cache output, logs, minified assets and source maps |
157
+ | Keep source and lexical chunks; skip embeddings | Lockfiles, license/author files, CSV/TSV/JSONL data, snapshots, generated code identified by common suffixes or an explicit generated/do-not-edit comment in the first 8 KiB |
158
+ | Keep source, lexical chunks and eligible embeddings | Authored code, tests, documentation, package manifests, CI/build configuration and other readable text |
159
+
160
+ `.env.example`, `.env.sample`, `.env.template` and equivalent suffixes remain
161
+ included as templates. Private-key PEM headers also exclude files with unrelated
162
+ extensions. These are targeted exclusions, **not a general secret scanner**;
163
+ review the dry-run inventory before uploading. `.gitignore` does not remove
164
+ already tracked Git objects, and `.gitattributes` is not interpreted for selection.
165
+
166
+ Use `--file-policy policy.json` with `repo add` or `import --dry-run --path` to
167
+ adjust the scope explicitly. The JSON contents are pinned in the repository
168
+ preset; subsequent connected imports use that preset, not the local policy file.
169
+
170
+ ```json
171
+ {
172
+ "version": 1,
173
+ "rules": [
174
+ { "pattern": "eval/**", "action": "exclude" },
175
+ { "pattern": "third_party/special/**", "action": "lexical" },
176
+ { "pattern": "generated/api.pb.go", "action": "semantic" }
177
+ ]
178
+ }
179
+ ```
180
+
181
+ Patterns match case-sensitive, repository-relative paths. `*` and `?` stay within
182
+ one path segment; `**` must occupy a whole segment and matches any depth. Rules
183
+ run in order; the last match wins. `semantic` permits embeddings when enabled but
184
+ still skips structural/import-only chunks. Rules override dependency/generated/
185
+ data defaults, but cannot override credential, crypto, image, binary, private-key
186
+ content, size, encoding, symlink or LFS exclusions. `retrieval` and `policyReason`
187
+ in dry-run coverage explain each included file's policy; chunk records retain
188
+ `embeddingSkipReason`. A changed policy selects a distinct Collection/configuration.
189
+
190
+ ```sh
191
+ srcx import --path . --ref develop --dry-run --embedding text-embedding-3-small --file-policy policy.json --output /tmp/srcx-preview
192
+ srcx repo add --path . --embedding text-embedding-3-small --file-policy policy.json
193
+ ```
194
+
195
+ Evaluation labels need an explicit corpus boundary. The checkout evaluation
196
+ harnesses use [this policy](eval/source-corpus-policy.json) to exclude `eval/**`;
197
+ labels stored elsewhere require additional exclusions before a new evaluation.
198
+ General-purpose imports do not discard all evaluation or test directories.
199
+
200
+ Java, TypeScript/TSX, JavaScript/JSX, Python, Go, Rust, C/C++, Shell and SQL use
201
+ pinned Tree-sitter WASM grammars.
202
+
203
+ | Language filter | File extensions | Boundaries and metadata |
204
+ | --------------- | -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
205
+ | `python` | `.py`, `.pyi` | Decorators, functions, classes, method scopes and docstrings |
206
+ | `go` | `.go` | Named types, functions and generic/pointer/value receiver scopes |
207
+ | `rust` | `.rs` | Functions, types and `impl`/`trait`/module scopes; outer attributes and doc comments stay with declarations |
208
+ | `c` | `.c`, `.h` | Functions, pointer declarators, types and preprocessor branches |
209
+ | `cpp` | `.cpp`, `.cc`, `.cxx`, `.C`, `.hpp`, `.hh`, `.hxx` | Functions, templates, namespace/class scopes and qualified names |
210
+ | `shell` | `.sh`, `.bash` | Bash-compatible functions and compound commands, including heredocs |
211
+ | `sql` | `.sql` | Statements, CTEs and supported function bodies; created object names/schema scopes |
212
+
213
+ `.h` files use the C grammar deterministically; C++ headers should use a listed
214
+ C++ extension for syntax chunking. Shell does not infer extensionless scripts from
215
+ shebangs or claim Zsh/Fish/PowerShell support. Shell and SQL use bundled
216
+ [grammar artifacts](runtime/grammars/README.md); SQL dialect-specific syntax unsupported
217
+ by that grammar falls back to text. SQL strings and supported dollar-quoted bodies
218
+ are parsed as part of their containing statement, not split at each semicolon.
219
+ Rust macros/`cfg` and C/C++ preprocessor conditions are not expanded or evaluated;
220
+ search uses authored source, including both conditional branches.
221
+
222
+ Markdown uses heading/paragraph/fence boundaries; configuration text uses
223
+ section/line boundaries. Parse errors and unsupported languages use recorded text
224
+ fallback. Chunks cover the exact source bytes, carry one-based line ranges, target
225
+ 800 tokens, and stay below 1,500 tokens including path/symbol context. The internal
226
+ window baseline is available to the test/build API, not as a public storage backend.
227
+
228
+ Added-language functions and SQL statements stay together when they fit the token
229
+ ceiling. Larger units use bounded text splitting with the same symbol/scope
230
+ metadata; nested functions remain inside their containing function. Syntax
231
+ unsupported by the pinned grammars uses recorded whole-file parse fallback.
232
+ Language labels remain available to `--language` filters even after fallback.
233
+
234
+ ## Choose text analyzers
235
+
236
+ New repositories use `standard` by default. Choose any nonempty combination of
237
+ LambdaDB's supported analyzers: `english`, `korean`, `japanese`, and `standard`.
238
+ These analyze searchable text; they are separate from programming-language
239
+ chunking and the `--language` file filter.
240
+
241
+ ```sh
242
+ srcx repo add --path /path/to/repo --analyzers english,korean
243
+ srcx repo add --path /path/to/repo --analyzers english
61
244
 
62
- Java, TypeScript/TSX, and JavaScript use pinned Tree-sitter WASM grammars. Markdown
63
- uses heading/paragraph/fence boundaries; configuration text uses section/line
64
- boundaries. Parse errors and unsupported languages use recorded text fallback.
65
- Chunks cover the exact source bytes, carry one-based line ranges, target 800 tokens,
66
- and stay below 1,500 tokens including path/symbol context. The internal window
67
- baseline is available to the test/build API, not as a public storage backend.
245
+ # Preview exactly the same settings without credentials or service calls.
246
+ srcx import --path /path/to/repo --ref main --dry-run \
247
+ --analyzers english,korean --output /tmp/srcx-preview
248
+ ```
249
+
250
+ Order and duplicates do not matter: `korean,english,english` selects the same
251
+ preset as `english,korean`. Unknown names and empty entries are rejected.
252
+ The chosen analyzers are stored in the repository preset, included in its
253
+ configuration hash, and checked against the Collection schema during discovery.
254
+ Different analyzer sets select separate Collections. Connected imports and
255
+ searches use the registered preset; `--analyzers` on import is only accepted with
256
+ `--dry-run --path`. Inspect the selection with `srcx repo show --repo <collection>`.
257
+
258
+ This pre-release preset now requires an explicit analyzer list. Older descriptors
259
+ and artifacts without it are not accepted; existing Collections are not changed
260
+ in place. A new registration/import uses the chosen preset.
261
+
262
+ Analyzers affect lexical search and the lexical part of hybrid search. They do
263
+ not translate queries or change the raw text sent to the embedding provider.
264
+ The same selection configures `searchText` and managed `embeddingText` text indexes.
265
+ See [LambdaDB text indexes](https://docs.lambdadb.ai/guides/collections/index-types#text).
266
+
267
+ ## Opt into managed embeddings
268
+
269
+ Supported models are `text-embedding-3-small` (1536 dimensions) and
270
+ `text-embedding-3-large` (3072 dimensions), both cosine. Use either name with
271
+ `--embedding`; each model/analyzer combination has a separate pinned preset and
272
+ Collection. Changing models requires a separate import.
273
+
274
+ LambdaDB generates vectors for meaningful code, tests and prose. Imports-only
275
+ and structural chunks remain lexical. The CLI uses LambdaDB credentials; it does not need an OpenAI key.
276
+ Source text sent for embedding and semantic/hybrid queries pass through LambdaDB
277
+ to OpenAI and incur usage charges. See [LambdaDB managed embeddings](https://docs.lambdadb.ai/guides/collections/managed-embeddings).
278
+
279
+ ```sh
280
+ # Offline preview: no upload or embedding request.
281
+ srcx import --path /path/to/repo --ref main --dry-run \
282
+ --embedding text-embedding-3-small --output /tmp/srcx-managed-preview
283
+
284
+ # Creates a separate Collection; existing lexical Collections stay usable.
285
+ srcx repo add --path /path/to/repo --embedding text-embedding-3-small
286
+ # Use the exact collection value returned above, especially with multiple presets.
287
+ srcx import --repo <collection> --ref main
288
+ srcx search --repo <collection> --version main --query "retry failed writes" --mode hybrid
289
+ srcx search --repo <collection> --version main --query "retry failed writes" --mode semantic
290
+ ```
291
+
292
+ Connected imports, including `--dry-run --repo`, use the selected repository's
293
+ pinned preset. `--embedding` on import is only for `--dry-run --path`.
294
+ `search` keeps `--mode lexical` as its default; semantic and hybrid require a
295
+ managed Collection. Hybrid uses LambdaDB RRF with identical filters on both legs.
296
+ Existing result handles, lexical config hashes and publication journals stay valid.
297
+
298
+ Local artifacts contain eligible `embeddingText` and input hashes, not vectors.
299
+ `counts.managed` and `counts.managedTokens` estimate the complete corpus's eligible
300
+ chunks and input tokens; `embedded=0` does not mean the server will skip them.
301
+ Publication requires valid generated vectors in the immutable candidate Tag,
302
+ plus the same exact payload/source checks as lexical publication. Unchanged
303
+ records are not uploaded again. Changed file chunks and uncertain write retries
304
+ may be embedded again; no global or query embedding cache is promised.
305
+
306
+ A small synthetic live check is available after building:
307
+
308
+ ```sh
309
+ npm run build
310
+ node --env-file=.env.local scripts/live-managed.mjs
311
+ ```
312
+
313
+ It uploads two synthetic commits, bounds document inputs to 10,000 estimated
314
+ tokens and issues four managed search queries plus lexical checks. It retains a
315
+ Collection, local fixture, artifacts, result handles and `.srcx/live-managed/report.json`.
316
+ Completed reruns preserve the original report and make no service calls; changed
317
+ runtime inputs require a fresh directory. Failed runs retain journals and reject
318
+ automatic replay. These are correctness checks, not retrieval-quality measurements.
319
+
320
+ ## Optional local Qwen reranker
321
+
322
+ `search --rerank qwen` reranks candidates from any retrieval mode with
323
+ [Qwen3-Reranker-0.6B](https://huggingface.co/Qwen/Qwen3-Reranker-0.6B/blob/e61197ed45024b0ed8a2d74b80b4d909f1255473/README.md).
324
+ It is off by default. Prepare Python 3.12+ and the model separately; npm does not
325
+ install Python dependencies or download model weights. From a checkout:
326
+
327
+ ```sh
328
+ python3.12 -m venv .srcx/qwen-venv
329
+ .srcx/qwen-venv/bin/pip install -r runtime/requirements.txt
330
+ .srcx/qwen-venv/bin/hf download Qwen/Qwen3-Reranker-0.6B \
331
+ --revision e61197ed45024b0ed8a2d74b80b4d909f1255473 \
332
+ config.json generation_config.json model.safetensors tokenizer.json tokenizer_config.json vocab.json merges.txt
333
+ export SRCX_RERANK_PYTHON="$PWD/.srcx/qwen-venv/bin/python"
334
+
335
+ srcx search --repo <collection> --version <commit> \
336
+ --query "retry failed writes" --mode semantic \
337
+ --rerank qwen --candidates 50 --limit 10
338
+ ```
339
+
340
+ For a global npm installation, the requirements file is at
341
+ `$(npm root -g)/@functional-systems/srcx/runtime/requirements.txt`; place the venv
342
+ in a persistent directory of your choice and use its absolute Python path.
343
+ `HF_HUB_CACHE` can select an existing Hugging Face cache for both download and
344
+ search. The worker loads only the pinned revision from that cache, offline.
345
+ `SRCX_RERANK_DEVICE` accepts `auto` (default: CUDA, then MPS, then CPU), `cuda`,
346
+ `mps`, or `cpu`. The current worker uses float32, SDPA and batch size one.
347
+
348
+ `--candidates` defaults to `max(50, limit)` and must be between `--limit` and 100.
349
+ It requires `--rerank qwen`. Both hybrid retrieval legs use this candidate limit;
350
+ path/language filters and the immutable version apply before reranking. The
351
+ worker receives the query and complete, verified source bytes of each chunk,
352
+ without a path prefix or evaluator labels. Identical source text shares a score
353
+ within the query; every candidate remains present and ties retain retrieval order.
354
+ It uses the code-search instruction from the CoSQA evaluation and ranks by the
355
+ raw yes-minus-no logit margin, not a calibrated relevance probability.
356
+
357
+ JSON stdout remains an array of results. `score` retains the retrieval score;
358
+ `rerankScore`, `retrievalRank` (one-based), and `reranker` identify the new order.
359
+ Only the returned results receive persisted evidence handles. Reranked excerpts
360
+ use the exact chunk bytes; normal reads still expand to complete source lines.
361
+ A JSON timing record on stderr reports verified retrieval, worker, search, and
362
+ command-handler times. Worker time includes Python startup, model loading and
363
+ inference. External process timing additionally includes Node startup and output.
364
+
365
+ Each CLI invocation loads a fresh model; this is an opt-in local integration,
366
+ not a warm inference service. The worker has a 120-second timeout, a 4 MiB input
367
+ cap and an 8,192-token limit per query/chunk pair. Missing setup, oversized input,
368
+ invalid scores and inference failures fail the command without silent truncation
369
+ or fallback. Empty candidate pools skip model execution. Existing search defaults
370
+ and managed embedding usage rules remain unchanged; wider pools increase source
371
+ verification work. See the [integration validation](VALIDATION.md#local-reranker-integration).
372
+
373
+ Failures include a fixed remediation message where the cause is known:
374
+
375
+ | Failure | Action |
376
+ | ------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
377
+ | Python executable missing or not executable | Check the path and execute permissions in `SRCX_RERANK_PYTHON`. |
378
+ | Missing or incompatible Python imports | Install `runtime/requirements.txt` using that Python environment. |
379
+ | Missing or incomplete model cache | Download the pinned revision and all files listed above; check `HF_HUB_CACHE`. |
380
+ | Invalid or unavailable device | Use `SRCX_RERANK_DEVICE=auto` or `cpu`, or an available `mps`/`cuda` device. |
381
+ | Request exceeds 4 MiB | Reduce `--candidates` or shorten the query. |
382
+ | A query/chunk pair exceeds 8,192 tokens | Shorten the query or omit `--rerank`; reducing candidate count does not shorten an individual chunk. |
383
+ | Worker exceeds 120 seconds | Reduce `--candidates` or select an available faster device. |
384
+
385
+ Unknown worker failures remain generic. Raw subprocess output and library
386
+ exceptions are never included in these messages. Failed reranking does not
387
+ silently return the original ranking; rerun without `--rerank` to opt out.
388
+
389
+ For practical search → read → change-planning examples, see the
390
+ [developer workflow pilot](https://github.com/lambdadb/srcx/blob/develop/eval/DEVELOPER-WORKFLOW-PILOT.md).
391
+ It follows three maintenance investigations through related source and tests,
392
+ including the limitations of previews and optional reranking.
393
+
394
+ The [agent workflow diagnostic](https://github.com/lambdadb/srcx/blob/develop/eval/AGENT-WORKFLOW-PILOT.md)
395
+ compares fresh agent sessions with Git/local tools and optional or explicitly
396
+ invoked srcx. It found no established efficiency advantage on the small public
397
+ corpora and records the remaining workflow hypotheses.
398
+
399
+ The [semantic agent follow-up](https://github.com/lambdadb/srcx/blob/develop/eval/SEMANTIC-AGENT-RESULTS.md)
400
+ compares local, lexical-first and semantic-first investigations on Requests. It
401
+ finds no established agent efficiency gain and records an unresolved candidate
402
+ retrieval discrepancy and excessive embedding of a generated SVG asset.
403
+
404
+ ## Query language and agent use
405
+
406
+ Queries can use any language; the CLI does not translate them. For lexical search,
407
+ match the language of the source you want to find. Prefer English search terms for
408
+ English code and comments, preserving identifiers, API names and error messages
409
+ exactly. For Korean documentation, use Korean terms in a Collection registered
410
+ with the `korean` analyzer. Analyzers tokenize text; they do not translate between
411
+ languages. The `--language` search filter selects a programming language, not the
412
+ natural language of the query.
413
+
414
+ For example, an agent answering the Korean question “데이터베이스 연결을 닫을 때
415
+ 어떻게 되나요?” can search English source with:
416
+
417
+ ```sh
418
+ srcx search --repo <collection> --version <commit> \
419
+ --query "What happens when closing a database connection?"
420
+ ```
421
+
422
+ This is a query-writing example, not a measured retrieval result. Read the returned
423
+ source before answering. Semantic and hybrid search can help across languages,
424
+ but relevant implementation evidence is not guaranteed to appear in the first
425
+ results. English wording is a starting point, not an input requirement or a
426
+ promise of better ranking for every question.
427
+
428
+ Agents can use the following search guidance:
429
+
430
+ > Choose query wording for the target source language, independently of the user's
431
+ > conversation language. For English code and comments, translate the user's
432
+ > intent into a concise English query. Preserve supplied identifiers, API names,
433
+ > paths and error messages exactly; do not invent implementation names or assume
434
+ > the question's premise is correct. Use the original language when seeking
435
+ > documentation written in that language. Read results at the pinned version and
436
+ > check that they support the answer. If evidence is incomplete, inspect relevant
437
+ > surrounding code or try another query based on observed source. Answer in the
438
+ > user's language and cite the source; state when evidence is missing.
439
+
440
+ ## Evaluate retrieval quality
441
+
442
+ The [fresh agent navigation comparison](https://github.com/lambdadb/srcx/blob/develop/eval/FRESH-AGENT-NAVIGATION-RESULTS.md)
443
+ measures complete answers, model input and wall time with local tools available in
444
+ both conditions. It does not establish a clear efficiency advantage on a small
445
+ local repository; retrieval quality and agent-workflow benefits remain separate.
446
+
447
+ The [cross-repository version workflow](https://github.com/lambdadb/srcx/blob/develop/eval/VERSION-WORKFLOW-RESULTS.md)
448
+ verifies exact source delivery across CLI/SDK releases from a fresh client without
449
+ local source attachments. It is a scripted known-range diagnostic, not an agent
450
+ benchmark. Local Git reads are much faster in this run; repeated project-wide
451
+ repository discovery is a measured source of remote overhead.
452
+
453
+ The internal [lexical chunking pilot](https://github.com/lambdadb/srcx/blob/develop/eval/README.md) compares syntax-aware and
454
+ window chunks on a fixed public corpus and 16 pinned investigation queries.
455
+ `npm run eval:prepare` builds and validates the comparison offline. Live evaluation
456
+ is an explicit separate operation and retains isolated evaluation Collections.
457
+
458
+ The [default CLI workflow evaluation](https://github.com/lambdadb/srcx/blob/develop/eval/CLI-WORKFLOW.md)
459
+ adds a second public repository and verifies real `search` → `read` results with
460
+ the unchanged CLI preset. It uses normal repository Collections and separate local
461
+ state; see its documented effects before opting into the live run.
462
+
463
+ The [retrieval mode comparison](https://github.com/lambdadb/srcx/blob/develop/eval/RETRIEVAL-MODES.md) runs lexical, semantic and
464
+ hybrid against the same managed corpora. It retains original and reviewed labels,
465
+ full stdout accounting, command timings and bounded embedding request estimates.
466
+ `npm run eval:modes:prepare` is offline; live execution is explicit and incurs
467
+ managed embedding and LambdaDB usage.
468
+
469
+ The [query-style diagnostic](https://github.com/lambdadb/srcx/blob/develop/eval/QUERY-STYLES.md)
470
+ pairs identifiers, natural-language descriptions and mixed questions on eight new
471
+ tasks. It adds rank-prefix and stdout-budget measurements without changing the
472
+ model or ranking. [Embedding model candidates](https://github.com/lambdadb/srcx/blob/develop/eval/EMBEDDING-MODELS.md)
473
+ separately describe possible follow-up comparisons and integration requirements.
474
+ The [managed model comparison](https://github.com/lambdadb/srcx/blob/develop/eval/MODEL-COMPARISON.md)
475
+ compares small and large on both frozen suites, including lexical controls.
476
+ [Results](https://github.com/lambdadb/srcx/blob/develop/eval/MODEL-COMPARISON-RESULTS.md)
477
+ show mixed gains and regressions; small remains the initial managed choice.
478
+
479
+ [Transfer evaluation preparation](https://github.com/lambdadb/srcx/blob/develop/eval/TRANSFER-EVAL.md) adds source-verified,
480
+ unreviewed Python/Go questions. The [completed development diagnostic](https://github.com/lambdadb/srcx/blob/develop/eval/TRANSFER-RESULTS.md)
481
+ compares all three modes with managed small and text fallback; it is not an
482
+ independently reviewed benchmark.
483
+ The [local reranking diagnostic](https://github.com/lambdadb/srcx/blob/develop/eval/RERANK-RESULTS.md)
484
+ compares Qwen selection on the same saved candidates, with separate offline
485
+ coverage and compute accounting.
486
+ The [public retrieval baseline](https://github.com/lambdadb/srcx/blob/develop/eval/PUBLIC-BENCHMARK.md)
487
+ uses pinned CoIR CoSQA and MTEB CodeSearchNet Python/Go tasks with official
488
+ labels and trec_eval metrics. It evaluates retrieval separately from Git import,
489
+ chunking and CLI reads.
490
+ New evaluation roots retain [safe command failure diagnostics](https://github.com/lambdadb/srcx/blob/develop/eval/COMMAND-DIAGNOSTICS.md)
491
+ for explicit recovery.
68
492
 
69
493
  ## Explicit live acceptance run
70
494
 
@@ -85,39 +509,87 @@ It saves connection settings under `.srcx/live/config.json` and keeps its state
85
509
  separate under `.srcx/live/state`. Rerunning resumes the saved synthetic run and
86
510
  refuses to reuse it against a different destination.
87
511
 
512
+ For persistent Git branch acceptance, run `npm run test:live:branches`. It uses a
513
+ separate synthetic Collection and `.srcx/live-branches/` state/report, covering
514
+ in-place A/B updates, last-published reads during a pending update, shared commit
515
+ Tags across two branches, rewinds, no-op imports, and SHA-only manual imports.
516
+ From an isolated worktree, load the original checkout's env file explicitly:
517
+
518
+ ```sh
519
+ npm run build
520
+ node --env-file=/absolute/path/to/srcx/.env.local scripts/live-branches.mjs
521
+ ```
522
+
523
+ The branch harness retains resources and resumes saved checkpoints on rerun.
524
+ It preserves the original source revision and completion time. Checkpoints from
525
+ different runtime code, harness, fixture, lockfile, or Node version are rejected
526
+ before connecting or overwriting evidence. To validate changed code, select a new
527
+ `SRCX_LIVE_BRANCHES_DIR` (for example `.srcx/live-branches-next`); retain the old
528
+ run and any pending journal. Its per-import deadline defaults to 300 seconds and accepts
529
+ `SRCX_LIVE_TIMEOUT_MS` up to 600000. Do not delete pending journals to start over.
530
+
88
531
  ## Connected workflow
89
532
 
533
+ Use the installed `srcx` binary below. For a source checkout, build first and
534
+ replace `srcx` with `node dist/cli.js`.
535
+
90
536
  These commands create and write LambdaDB resources. Select an approved project
91
- and source scope before running them. Start live validation with the synthetic
92
- fixture, not a production repository.
537
+ and source scope before running them. Start live validation with a small synthetic
538
+ fixture. `repo add` returns a `collection` value: use that value as `<name>` below
539
+ to disambiguate repositories with multiple presets. If isolating a first-use run,
540
+ set `SRCX_CONFIG` and `SRCX_STATE_DIR` to fresh paths before `configure`; keep
541
+ credentials in the shell and preserve these paths for later result reads.
93
542
 
94
543
  ```sh
95
544
  # Supply LAMBDADB_API_KEY through your shell or secret manager.
96
- node dist/cli.js configure --endpoint https://api.lambdadb.ai --project <project>
97
- node dist/cli.js doctor
98
- node dist/cli.js repo add --path /path/to/repo \
545
+ srcx configure --endpoint https://api.lambdadb.ai --project <project>
546
+ srcx doctor
547
+ srcx repo add --path /path/to/repo \
99
548
  --description "Repository source, tests, and documentation for code search." \
100
549
  --tag team=search
101
- node dist/cli.js repo list
102
- node dist/cli.js repo show --repo <name>
550
+ srcx repo list
551
+ srcx repo show --repo <name>
103
552
 
104
553
  # Import the exact artifact reviewed in the credential-free preview.
105
- node dist/cli.js import --repo <name> --artifact /tmp/srcx-build-a
106
- node dist/cli.js versions --repo <name>
107
- node dist/cli.js search --repo <name> --version <full-commit-A> --query retry
108
- node dist/cli.js read --result <result-id> --context 20
109
- node dist/cli.js read --result <result-id> --full-file
110
- node dist/cli.js read --repo <name> --version <full-commit-A> \
554
+ srcx import --repo <name> --artifact /tmp/srcx-build-a
555
+ srcx versions --repo <name>
556
+
557
+ # Keep a Git branch connected to its Collection Branch.
558
+ srcx import --repo <name> --ref develop
559
+ srcx search --repo <name> --version develop --query retry
560
+ srcx resolve --repo <name> --ref refs/heads/develop
561
+ srcx search --repo <name> --version <full-commit-A> --query retry
562
+ srcx read --result <result-id> --context 20
563
+ srcx read --result <result-id> --implementation
564
+ srcx read --result <result-id> --full-file
565
+ srcx read --repo <name> --version <full-commit-A> \
111
566
  --path src/example.ts --lines 10:30
112
567
 
113
- node dist/cli.js import --repo <name> --artifact /tmp/srcx-build-b
568
+ srcx import --repo <name> --artifact /tmp/srcx-build-b
114
569
  # An old A result still reads A after B is published.
115
- node dist/cli.js read --result <result-id> --full-file
570
+ srcx read --result <result-id> --full-file
116
571
 
117
- node dist/cli.js git sync-tags --repo <name>
118
- node dist/cli.js resolve --repo <name> --ref v1.0.0
572
+ srcx git sync-tags --repo <name>
573
+ srcx resolve --repo <name> --ref v1.0.0
119
574
  ```
120
575
 
576
+ `read --implementation` follows a contiguous Python or TypeScript/TSX overload
577
+ group to its unique implementation in the same file and AST scope. It reads the
578
+ stored source at the result's immutable Tag; no reindexing or embedding is needed.
579
+ Python supports direct `from typing`/`typing_extensions import overload` imports,
580
+ including aliases used only as decorators. Stub files, ambiguous/interrupted
581
+ groups, unrecognized decorators and parse failures retain the original span.
582
+ Other languages and cross-file/type-based dispatch are not resolved. This is
583
+ syntax navigation, not proof of runtime binding or behavior.
584
+
585
+ The returned `implementation.status` is `resolved`, `not-linked`, `unsupported`,
586
+ `parse-error` or `too-large`. Resolved reads return the body's actual lines and
587
+ citation. Multiple overload hits may return the same body; the option does not
588
+ deduplicate results or skip reads. Bodies exceeding 1,500 source tokens retain the
589
+ original span with `too-large`; no silent truncation is applied. Ordinary reads
590
+ and search rankings are unchanged. The option requires `--result` and cannot be
591
+ combined with `--context`, `--lines` or `--full-file`.
592
+
121
593
  `doctor` checks authentication and Collection read access, not write permission
122
594
  or indexing/query readiness. `configure --api-key-env NAME` selects another
123
595
  credential environment variable; only its name is stored. Endpoint/project changes
@@ -131,7 +603,9 @@ identity or Collection name. Registration normalizes the selected Git remote;
131
603
  without remotes receive a persistent local source identity. Repeated registration
132
604
  preserves existing descriptions/labels and attaches the local checkout.
133
605
 
134
- Search is literal analyzed lexical text, restricted to `kind=chunk`. Optional
606
+ Search defaults to literal analyzed lexical text. All retrieval modes are
607
+ restricted to `kind=chunk`; semantic/hybrid and optional Qwen reranking are
608
+ described above. Optional
135
609
  `--path` and `--language` filters are exact keyword filters. `--limit` is 1–100.
136
610
  Search results include a durable local `resultId`, commit, immutable Tag/Snapshot,
137
611
  path, lines, and citation. Reads verify the original content hash and refuse
@@ -141,10 +615,28 @@ are one-based and inclusive.
141
615
  ## Publication and recovery
142
616
 
143
617
  The control Branch `main` holds descriptors/version summaries. `checkpoint-empty`
144
- is forked before any control write. Each import uses a new `work-*` Branch,
145
- optionally forked from the last locally retained, remotely validated writer
146
- baseline. Writers are frozen after publication. A fresh local state can start a
147
- full import from `checkpoint-empty`; source data is never forked from a Tag.
618
+ is forked before any control write. Importing a Git branch creates or updates its
619
+ stable `git-*` Collection Branch, derived from the full `refs/heads/...` name.
620
+ Git `main` also uses a `git-*` Branch; Collection `main` remains control-only.
621
+ Each later import reconciles against that branch's last validated snapshot,
622
+ including deletions and non-fast-forward changes. Branches sharing a commit share
623
+ one canonical `ver-*` Tag while retaining their own writer snapshots.
624
+
625
+ `search/read --version develop` and `resolve --ref develop` select the branch's
626
+ last successfully published commit Tag. During an import or after a failed update,
627
+ they keep serving the previous published commit; the first import is unavailable
628
+ until publication. This is the last indexed state, not a live Git HEAD lookup.
629
+ Nothing polls or fetches Git automatically: run import again to advance the branch.
630
+ If an indexed branch and synchronized Git tag share a short name, use
631
+ `refs/heads/<name>` or `refs/tags/<name>` explicitly. Known Git names take precedence
632
+ over commit prefixes.
633
+
634
+ A commit SHA or Git tag import does not infer a containing branch. An unpublished
635
+ commit uses a fresh `work-*` Branch, optionally forked from a validated previous
636
+ manual writer; an already published commit reuses its Tag. Manual writers remain
637
+ frozen. Source data is never forked from a Tag. A clean tracked branch can be
638
+ updated from fresh local state using its remote baseline. Local build reuse is
639
+ cached separately for each Git branch and for manual imports.
148
640
 
149
641
  The importer deletes obsolete IDs, upserts changed records and inventory parts in
150
642
  bounded sequential requests, then sends `__manifest__` **alone** after every prior
@@ -156,7 +648,10 @@ an early/stale snapshot even after the marker is observed.
156
648
 
157
649
  A per-Collection local lock and durable `pending.json` journal prevent another
158
650
  commit from overwriting a partial attempt. Only one importing host is supported.
159
- After a timeout or unknown write result, retain the artifacts and journal:
651
+ A tracked branch also records pending import ownership in control `main` before
652
+ writing code. If the local journal is lost, new local state refuses to overwrite
653
+ that pending branch even when its committed head has not advanced yet. After a
654
+ timeout or unknown write result, retain the artifacts and journal:
160
655
 
161
656
  ```sh
162
657
  node dist/cli.js import --repo <name> --artifact /path/from/pending.json \
@@ -184,8 +679,17 @@ For search and resolve, a synchronized Git tag name takes precedence over a comm
184
679
  prefix, matching Git import's tag-before-OID rule. A pending tag fails explicitly
185
680
  instead of falling back to a matching commit prefix. Use `refs/tags/<name>` to
186
681
  select a Git tag explicitly.
187
- Explicit authoritative pruning and persistent tracked-branch synchronization are
188
- follow-up work; no full history import is required.
682
+ Automatic Git observation, authoritative pruning, branch rename/deletion handling,
683
+ and garbage collection remain follow-up work; no full history import is required.
684
+
685
+ Existing commit Tags and frozen `work-*` Branches remain valid. The next import
686
+ using a Git branch name establishes its fixed mapping, even if that commit was
687
+ already published. A pending journal from the previous implementation resumes on
688
+ its original `work-*` writer; import the branch again after recovery to establish
689
+ tracking. `--artifact` uses the Git branch recorded when the artifact was built,
690
+ with its pinned commit; it does not reread the branch's current tip. The publication
691
+ JSON continues to describe the canonical commit Tag: its `writer` can be the
692
+ original publishing branch when multiple Git branches share that commit.
189
693
 
190
694
  ## State and implementation map
191
695