@functional-systems/srcx 0.1.0-dev.4 → 0.1.0-dev.40

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 (66) hide show
  1. package/CHANGELOG.md +179 -0
  2. package/CONTRIBUTING.md +4 -0
  3. package/DESIGN.md +378 -58
  4. package/README.md +628 -35
  5. package/RELEASING.md +15 -3
  6. package/VALIDATION.md +1120 -16
  7. package/dist/artifact.d.ts +31 -0
  8. package/dist/artifact.js +237 -0
  9. package/dist/artifact.js.map +1 -0
  10. package/dist/build.d.ts +86 -3
  11. package/dist/build.js +233 -71
  12. package/dist/build.js.map +1 -1
  13. package/dist/chunk.d.ts +9 -3
  14. package/dist/chunk.js +341 -14
  15. package/dist/chunk.js.map +1 -1
  16. package/dist/cli.js +130 -21
  17. package/dist/cli.js.map +1 -1
  18. package/dist/file-policy.d.ts +20 -0
  19. package/dist/file-policy.js +103 -0
  20. package/dist/file-policy.js.map +1 -0
  21. package/dist/implementation.d.ts +11 -0
  22. package/dist/implementation.js +191 -0
  23. package/dist/implementation.js.map +1 -0
  24. package/dist/publish.d.ts +18 -0
  25. package/dist/publish.js +224 -46
  26. package/dist/publish.js.map +1 -1
  27. package/dist/releases.js +21 -3
  28. package/dist/releases.js.map +1 -1
  29. package/dist/remote.d.ts +1 -0
  30. package/dist/remote.js +50 -9
  31. package/dist/remote.js.map +1 -1
  32. package/dist/repository.d.ts +4 -1
  33. package/dist/repository.js +26 -11
  34. package/dist/repository.js.map +1 -1
  35. package/dist/rerank.d.ts +16 -0
  36. package/dist/rerank.js +87 -0
  37. package/dist/rerank.js.map +1 -0
  38. package/dist/search.d.ts +18 -3
  39. package/dist/search.js +143 -23
  40. package/dist/search.js.map +1 -1
  41. package/dist/skills.d.ts +24 -0
  42. package/dist/skills.js +155 -0
  43. package/dist/skills.js.map +1 -0
  44. package/package.json +17 -6
  45. package/runtime/grammars/README.md +50 -0
  46. package/runtime/grammars/tree-sitter-bash.LICENSE +21 -0
  47. package/runtime/grammars/tree-sitter-bash.wasm +0 -0
  48. package/runtime/grammars/tree-sitter-sql.LICENSE +21 -0
  49. package/runtime/grammars/tree-sitter-sql.wasm +0 -0
  50. package/runtime/grammars/tree-sitter-wasm.LICENSE +21 -0
  51. package/runtime/qwen.py +132 -0
  52. package/runtime/requirements.txt +34 -0
  53. package/skills/srcx-search/SKILL.md +103 -0
  54. package/src/artifact.ts +303 -0
  55. package/src/build.ts +313 -84
  56. package/src/chunk.ts +360 -12
  57. package/src/cli.ts +263 -23
  58. package/src/file-policy.ts +166 -0
  59. package/src/implementation.ts +253 -0
  60. package/src/publish.ts +321 -47
  61. package/src/releases.ts +36 -3
  62. package/src/remote.ts +70 -13
  63. package/src/repository.ts +40 -11
  64. package/src/rerank.ts +131 -0
  65. package/src/search.ts +229 -28
  66. package/src/skills.ts +205 -0
package/DESIGN.md CHANGED
@@ -1,10 +1,11 @@
1
1
  # srcx: Initial Implementation Design
2
2
 
3
- Status: initial CLI implemented with local tests and live synthetic A/B validation
4
- on LambdaDB. See [README.md](README.md) for runnable interfaces and
3
+ Status: CLI implemented with persistent Git branch tracking, managed semantic/hybrid
4
+ search and optional local Qwen reranking. Local, live and public-benchmark evidence
5
+ have separate scopes. See [README.md](README.md) for runnable interfaces and
5
6
  [VALIDATION.md](VALIDATION.md) for the bounded live evidence and remaining scope.
6
7
 
7
- Updated: 2026-09-25.
8
+ Updated: 2026-09-26.
8
9
 
9
10
  ## 1. Purpose, decisions, and implementation defaults
10
11
 
@@ -18,14 +19,13 @@ supporting each result. The project name is `srcx`.
18
19
  | --- | --- |
19
20
  | Project and display name | `srcx` |
20
21
  | Local directory | `srcx` |
21
- | Intended GitHub repository | `lambdadb/srcx` |
22
+ | GitHub repository | `lambdadb/srcx` |
22
23
  | CLI executable | `srcx` |
23
- | Intended npm package | `@functional-systems/srcx` |
24
+ | npm package | `@functional-systems/srcx` |
24
25
  | Short description | Version-aware code search on LambdaDB |
25
26
 
26
- The name is selected; the GitHub repository and npm package have not been created
27
- or published in this project. The package manifest and executable entry point are
28
- present in the initial CLI. Keep display/configuration naming centralized and
27
+ The public GitHub repository and npm development channel are available. Current
28
+ publication evidence and stable-release status are recorded in RELEASING.md. Keep display/configuration naming centralized and
29
29
  distribution identity in `package.json`. Database IDs and the existing
30
30
  `code-*` Collection naming and `purpose=code-search-v1` protocol marker remain
31
31
  independent of the product name.
@@ -40,7 +40,7 @@ Confirmed boundaries from the discussion:
40
40
  - Map each Git tag to a LambdaDB Alias targeting its published commit Tag.
41
41
  Multiple Git tags for the same commit share one commit Tag and Snapshot.
42
42
  - Keep search results and subsequent source reads pinned to the selected version.
43
- - Replace a changed file's entire chunk set initially; cache embeddings by input.
43
+ - Replace a changed file's entire chunk set initially; retain unchanged remote records.
44
44
  - Keep core LambdaDB work, GitHub App/webhooks, UI, MCP, and a public SaaS outside
45
45
  the first deliverable. sbrain reference documents remain unchanged.
46
46
  - No remote repository creation, application commit, push, publication, real
@@ -53,7 +53,7 @@ Current recommendations, distinguished from user-confirmed choices:
53
53
  | Runtime | TypeScript and a supported Node.js release compatible with the existing SDK |
54
54
  | Database | LambdaDB only; no public backend selection or interchangeable database framework |
55
55
  | API key | Read `LAMBDADB_API_KEY` by default; optional environment-variable-name override |
56
- | Syntax | Java and TypeScript/JavaScript first; other text uses recorded fallback |
56
+ | Syntax | Java, TypeScript/JavaScript, Python, Go, Rust, C/C++, Shell and SQL; other text uses recorded fallback |
57
57
  | Source | Exact UTF-8 source inside file documents, with local blob cache |
58
58
  | File size | Start with a 1 MiB raw-source limit and explicit exclusions |
59
59
  | Embedding | A fixed `none` preset first; with a model, embed meaningful code and prose chunks while recording policy-based skips |
@@ -72,9 +72,10 @@ This document is not a deployed-revision audit or evidence of a passing live run
72
72
 
73
73
  The initial command set below is implemented; run it as `node dist/cli.js` from
74
74
  this checkout after `npm run build`. See README for exact options and recovery.
75
- The first implementation uses fresh `work-*` Branches and observed-local-tag Alias
76
- synchronization; persistent tracked branches and authoritative pruning remain
77
- follow-up work. Immutable manifest `requestedRef` is normalized to the resolved
75
+ Git branch imports now reuse persistent `git-*` Branches; explicit commit/tag
76
+ imports use frozen `work-*` writers. Observed-local-tag Alias synchronization is
77
+ implemented; automatic Git observation and authoritative pruning remain follow-up
78
+ work. Immutable manifest `requestedRef` is normalized to the resolved
78
79
  commit OID; the
79
80
  original user spelling remains in the local build artifact. The broader contract
80
81
  below remains the target design.
@@ -379,18 +380,30 @@ readers on multiple machines do not require local registration state.
379
380
  changed/deleted file, compute obsolete IDs as previous file/chunk IDs minus
380
381
  replacement IDs. A deleted file has an empty replacement set. Obtain previous
381
382
  IDs from the inventory, not mutable query-by-path results.
382
- 6. Apply the pinned per-chunk embedding policy. If embeddings are enabled, batch
383
- eligible cache misses across chunks/files within the provider's token/request
384
- limits. Validate successful vectors before caching.
383
+ 6. Apply the pinned per-chunk embedding policy. The managed preset materializes
384
+ eligible `embeddingText` inputs without calling a provider locally. LambdaDB
385
+ generates vectors during ordinary upsert. Skip unchanged remote records and
386
+ validate generated vectors in the candidate Tag before publication.
385
387
  Bound queue memory; do not load an entire repository's content into RAM.
386
388
  7. Materialize deterministic records and deletion lists as local build artifacts.
387
389
  Produce size-bounded inventory parts and a root manifest template. Check all
388
390
  serialized sizes and record-set hashes before starting uploads. The execution
389
391
  journal supplies the separate attempt ID when sealing the final manifest.
390
392
 
393
+ Local `records.jsonl` output batches complete canonical record lines in a 64 KiB
394
+ buffer, flushing before a line would exceed that bound. Larger individual lines
395
+ are written directly after flushing earlier records. Hash the existing canonical
396
+ representation, which is byte-equivalent to hashing the record object, rather
397
+ than serializing the object again. Flush all records before writing build metadata
398
+ and running full artifact validation. Write failures remove the partial output
399
+ directory; previous artifacts remain untouched. This changes write-call overhead,
400
+ not artifact bytes, order, schema or validation requirements.
401
+
391
402
  Dry-run executes the same inventory/chunking path but performs no database mutation
392
- or embedding call. For pending embedding misses, report tokens and projected vector
393
- size separately; do not claim a completed vector/records hash. Report every entry,
403
+ or embedding call. Report `managed` eligible chunks and `managedTokens` (estimated
404
+ input tokens for the complete corpus), with `embedded=0` in the local artifact.
405
+ These are not billed usage or incremental upload counts. Record hashes bind the
406
+ submitted payload; server-generated vectors are validated separately. Report every entry,
394
407
  exclusion reason, parse status, byte size, chunk/token counts, embedding eligibility
395
408
  and skip reasons, and change summary. Dry-run plans may show pending embedding work;
396
409
  published chunk records may not silently treat missing required vectors as skips.
@@ -418,6 +431,17 @@ connection or remote repository lookup. No `--backend` option is needed for that
418
431
  Use ordinary SDK upsert/delete for this workaround. Bulk ingestion remains later
419
432
  work; do not assume its asynchronous processing obeys the same marker ordering.
420
433
 
434
+ For baseline comparison, prefer a local artifact only after matching repository,
435
+ configuration, commit, build, record and inventory identities to the journal's
436
+ remote baseline, checking its Tag/Snapshot and manifest, and fully validating the
437
+ artifact. Reconstruct the old file/chunk and metadata hash map from that artifact.
438
+ The local artifact is a cache, never publication evidence: missing files or a
439
+ different build fall back to the immutable baseline's full listing; corruption
440
+ of a matching artifact fails closed. A write-stage retry uses the same rule and
441
+ does not require the previous local artifact. Compare inventory-part hashes too,
442
+ so unchanged metadata parts are not uploaded again. Always write the new root
443
+ marker separately after all required mutation ACKs.
444
+
421
445
  ### Replacing one file
422
446
 
423
447
  Replace a modified file's chunk set as a unit in the build plan, using the previous
@@ -436,6 +460,149 @@ record and 20 chunk records; these can share upload requests with other files.
436
460
  Original text appears once in its file record, with exact source ranges in chunks.
437
461
  Search context can repeat in chunk search text without changing the quoted source.
438
462
 
463
+ ### Experimental segmented local artifacts
464
+
465
+ Status: opt-in implementation. `import --artifact-storage segments` writes local
466
+ format 2; the default remains format 1 and a single `records.jsonl`. Presets,
467
+ remote schema, publication ordering and full validation are unchanged. See the
468
+ storage-only prototype and integrated-build measurements in `VALIDATION.md`.
469
+
470
+ The segmented layout uses one logical segment per included file: the exact
471
+ file record followed by all of its chunks, in ordinal order. A new artifact owns
472
+ all objects it needs. It may share physical storage through hardlinks, but never
473
+ depends on a previous artifact's directory, a global cache, or the current Git
474
+ checkout after construction. This targets retained-record rewrites; it does not
475
+ make full validation proportional to the delta.
476
+
477
+ The segmented descriptor extends the local storage version only:
478
+
479
+ ```ts
480
+ type RecordPart = {
481
+ fileId: string;
482
+ digest: string; // SHA-256 of exact canonical UTF-8 JSONL, including newlines.
483
+ byteLength: number;
484
+ recordCount: number;
485
+ };
486
+
487
+ // Existing logical Build fields remain unchanged.
488
+ // `directory` is resolved at load time, never used as an external object pointer.
489
+ type SegmentedBuild = Omit<Build, "format"> & {
490
+ format: 2;
491
+ recordParts: RecordPart[];
492
+ };
493
+ ```
494
+
495
+ Objects live at `objects/<64-lowercase-hex-digest>.jsonl` beneath the artifact.
496
+ Ordered references preserve the builder's existing changed-then-retained record
497
+ order, with no excluded-file segments. Full inventory entries, `recordHashes`,
498
+ counts and aggregate hashes remain in `build.json`. This keeps logical
499
+ identity independent of physical layout: for the same repository/commit/config,
500
+ changing only storage layout retains `buildId`, `configHash`, `recordsHash` and
501
+ `inventoryHash`. Object digests add storage integrity checks; they do not replace
502
+ record/source checks.
503
+
504
+ Require exactly one part per included inventory file, no duplicate file references,
505
+ and `recordCount === 1 + chunkIds.length` for that file. Each object must begin with
506
+ its referenced file record and contain only that file's expected chunks. Byte and
507
+ record counts must be positive safe integers, not allocation instructions from
508
+ untrusted metadata.
509
+
510
+ The writer and full validator follow these rules:
511
+
512
+ 1. Fully validate the previous artifact before reusing its records or hashes.
513
+ Keep the existing repository/configuration and Git blob/mode reuse conditions.
514
+ For a format-2 previous build, find retained objects from its validated file
515
+ inventory and part mapping; avoid the extra whole-record copy pass.
516
+ 2. Stream added/modified file groups to unique temporary objects, with the current
517
+ per-document size checks and bounded write buffer. Hash actual serialized
518
+ bytes, close each object and install it under its digest. Do not buffer an
519
+ entire file's chunk set in memory or impose an arbitrary new segment-size cap.
520
+ 3. Hardlink retained objects into the new artifact, using exclusive destination
521
+ creation. `EXDEV`, `ENOTSUP`, `EOPNOTSUPP` and `ENOSYS` use exclusive copy
522
+ fallback. Other I/O, missing-object or permission failures remain failures.
523
+ No destination reference may point back into the previous directory.
524
+ 4. Keep new output private to its attempt. Finish all objects before installing
525
+ the descriptor, then run complete validation against the new artifact. Object
526
+ write failures remove only that attempt's partial output. Interrupted output
527
+ is never accepted because a descriptor or marker exists. Atomic rename alone
528
+ is not an fsync or power-loss durability guarantee.
529
+ 5. On every full validation, check descriptor shape and logical membership,
530
+ recompute each referenced object's byte digest/count, and run all existing
531
+ uniqueness, record-hash, exact source/position/token and embedding-input checks.
532
+ A valid digest or matching count cannot establish that an old file belongs to
533
+ the new build. Retained records are not sampled or exempted.
534
+ 6. Reject arbitrary object paths, symlink objects/directories and special files.
535
+ Use digest-derived paths, `O_NOFOLLOW | O_NONBLOCK` file opens and post-open
536
+ regular-file/size checks, plus a local regular-directory check. The feature
537
+ requires native no-follow support; the local measurements use macOS. The existing
538
+ single-host model assumes importer-owned artifact directories; hostile
539
+ concurrent directory replacement by the same OS user is outside that model.
540
+ Keep one open record handle and bounded UTF-8 line decoding, retaining the
541
+ existing largest-document allowance. File mode, inode identity, mtime and a
542
+ previous validation receipt are not integrity proofs.
543
+
544
+ The shared `records()` iterator verifies object digests when fully consumed, as
545
+ `validateBuild()` always does. Partial consumers do not establish completeness;
546
+ publication readiness probes follow full build validation. No persistent
547
+ validation receipt skips object/record/source checks on restart.
548
+
549
+ Hardlinks reduce copying but do not enforce immutability: a write to one shared
550
+ inode can corrupt several local artifacts. Rehashing and complete source checks
551
+ must detect this on every use. Read-only modes can be defense in depth only.
552
+ Remote published Tags remain the authority for immutable version reads and do
553
+ not depend on the survival or integrity of local hardlinks.
554
+
555
+ | Condition | Required behavior |
556
+ | --- | --- |
557
+ | Previous directory deleted after the new build | New artifact remains self-contained and validates. |
558
+ | Artifact copied or relocated | Resolve all references beneath the new directory; no original paths needed. |
559
+ | Missing/corrupt object in the pending build | Fail before corpus mutation; retain the journal. Never substitute the current Git tip. |
560
+ | Previous local build entirely absent | Preserve the existing cold-build/remote-baseline recovery paths. |
561
+ | Missing object in an otherwise present previous build | Preserve the current missing-record validation failure; no silent reuse of metadata. |
562
+ | Previous local cache unavailable during publication retry | Validate the intact pending artifact and use its journal's immutable remote baseline, as today. |
563
+ | Corrupt matching local baseline cache | Preserve fail-closed validation rather than trusting its declared hashes. |
564
+ | Cross-filesystem link failure | Explicit copy fallback writes retained bytes too; no delta-write claim for that path. |
565
+ | Partial object/descriptor write or stale local receipt | Remain unpublished; reconstruct only from the exact original build identity or restore matching objects. |
566
+
567
+ No global shared-object garbage collector is needed:
568
+ deleting one artifact unlinks its own objects without invalidating other hardlinks.
569
+ Do not prune local artifacts associated with an active journal or claim this
570
+ implements remote version retention/cleanup.
571
+
572
+ Runtime integration and compatibility:
573
+
574
+ - The storage-format reader/descriptor validator retains legacy format-1 reads
575
+ and resumption. Internal readers accept the already loaded Build, avoiding
576
+ repeated parsing of a large descriptor. Directory-based callers load its
577
+ `build.json`. Unknown formats and missing format-2 descriptors/objects fail;
578
+ they do not fall back to a stray
579
+ `records.jsonl` merely because it exists.
580
+ - `--artifact-storage jsonl|segments` selects storage for a new build and defaults
581
+ to `jsonl`, even when the previous artifact is segmented. Initial conversion
582
+ from format 1 requires the full retained-record pass. Existing `--artifact`
583
+ imports use the recorded format and reject an explicit storage override.
584
+ Preview JSON adds `artifactFormat` (1 or 2); the remaining logical fields and
585
+ exit codes are unchanged. Storage selection is not an embedding preset change.
586
+ - `validateBuild`, previous-record reuse, publication readiness probes and
587
+ changed-record uploads use the shared reader. Full candidate validation,
588
+ final-marker ordering and managed-vector validation/hydration remain intact.
589
+ - Default JSONL evaluation fixtures and frozen archive byte hashes remain format
590
+ 1. Consumers reading `records.jsonl` directly must opt into the shared reader
591
+ before accepting format 2; they are not automatically migrated. Installed-package
592
+ lexical/managed CLI tests cover segmented resumption, loss of the previous local
593
+ artifact, tracked imports and immutable reads.
594
+
595
+ Default promotion requires end-to-end measurements including descriptor bytes, initial
596
+ conversion, full validation, cold recovery, cross-filesystem copies and bounded
597
+ memory/open handles. The prototype reduces record payload writes but adds many
598
+ file operations and shows slower validation. Integrated builds also trade speed
599
+ for materially lower writes and additional allocated storage. This justifies an
600
+ explicit experimental choice, while format 1 remains the default. Pack-based physical
601
+ storage or batched reads can be investigated later if per-file open/link overhead
602
+ dominates; neither is silently assumed by this implementation. Skipping full remote
603
+ candidate verification still requires the separate verified backend contract
604
+ described in section 9. Dependency ingestion remains outside this work.
605
+
439
606
  ## 7. Code-search schema v1
440
607
 
441
608
  The Collection uses one sparse document schema with `kind` distinguishing file,
@@ -473,11 +640,12 @@ fields are omitted when absent; records of different kinds need not share them.
473
640
  | Record | Additional stored fields |
474
641
  | --- | --- |
475
642
  | File (`kind=file`) | `path`, `blobOid`, `contentHash`, `byteLength`, `sourceText`, `language`, `parseStatus`, `chunkCount` |
476
- | Chunk (`kind=chunk`) | `fileId`, `path`, parent `contentHash`, `language`, `chunkKind`, `startByte`, `endByte`, `startLine`, `endLine`, `ordinal`, `searchText`, `embeddingStatus`; optional `symbol`, `scope`, `signature`, `embeddingSkipReason`, `embeddingInputHash`, `embedding` |
643
+ | Chunk (`kind=chunk`) | `fileId`, `path`, parent `contentHash`, `language`, `chunkKind`, `startByte`, `endByte`, `startLine`, `endLine`, `ordinal`, `searchText`, `embeddingStatus`; optional `symbol`, `scope`, `signature`, `embeddingSkipReason`, `embeddingInputHash`, `embeddingText`, `embedding` |
477
644
  | Corpus root (`kind=manifest`, `role=corpus`, ID `__manifest__`) | `repoId`, `indexId`, full `commitOid`, `commitTime`, `requestedRef`, full `config`, `inventoryHash`, `recordsHash`, `counts`, `buildId`, `attemptId`, `inventoryPartIds` |
478
645
  | Inventory part (`kind=manifest`, `role=inventory`) | `partOrdinal`, `partHash`, ordered `entries` with path, file/chunk IDs, blob/content identities, inclusion/exclusion reasons, parse states, sizes, and embedding coverage |
479
646
  | Repository control (`kind=manifest`, `role=repository`, main ID `__repo__`) | Full source identity, repo/index IDs, immutable preset/config, initialization state |
480
- | Ref control (`kind=manifest`, `role=git-ref`, main) | Full Git ref name, encoded Alias/Branch name, observed commit/time, applied version and synchronization state |
647
+ | Git tag control (`kind=manifest`, `role=git-ref`, main) | Full Git tag ref, encoded Alias name, observed commit, applied version and synchronization state |
648
+ | Git branch control (`kind=manifest`, `role=git-branch`, main) | Full Git branch ref, encoded Branch name, validated writer baseline, canonical published Tag and pending attempt identity |
481
649
  | Validation summary (`kind=manifest`, `role=validation`, main) | Candidate name/Snapshot, build/config/attempt identity, verifier version and checked counts/hashes; no premature claim of publication |
482
650
 
483
651
  `startByte`/`endByte` are half-open; display lines are one-based/inclusive.
@@ -486,8 +654,13 @@ content such as function, declaration, documentation, imports, or fallback; it i
486
654
  separate from the file/chunk/manifest discriminator. `counts` includes included and
487
655
  excluded files, chunks, and embedded/skipped chunks with reason totals.
488
656
 
489
- In a completed corpus, `embeddingStatus=embedded` requires a valid vector and
490
- `embeddingInputHash`, and omits the skip reason. `embeddingStatus=skipped` requires
657
+ The managed preset uses `embeddingStatus=managed` to identify its generation policy,
658
+ not local completion. Eligible chunks carry `embeddingText=searchText` and an
659
+ `embeddingInputHash` over the exact input and embedding configuration; ordinary
660
+ upserts omit `embedding`. A completed candidate must contain a nonzero, finite
661
+ 1536-number vector for every eligible chunk. Local artifacts contain no vectors.
662
+ The internal fixture-only client embedder retains `embeddingStatus=embedded`;
663
+ its arbitrary presets cannot be published through the CLI. `embeddingStatus=skipped` requires
491
664
  an explicit policy reason and omits the vector and input hash. The lexical-only
492
665
  preset records `embedding-disabled`; an embedding-enabled preset records its
493
666
  specific exclusion reason. Pending or failed required embedding work stays in the
@@ -543,15 +716,24 @@ is stored in the file; enriched chunk search text is never the citation authorit
543
716
  `sourceText`, role, byte/line positions, hashes, commit identity, scope/signature,
544
717
  embedding diagnostics, and inventory/config objects are stored without entries in
545
718
  `indexConfigs`. Public documentation states that fields are stored even when not
546
- indexed. Do not invent an `index: false` option. The `standard` analyzer is a
547
- baseline, not a proven code-specific ranking solution. An initial enrichment
719
+ indexed. Do not invent an `index: false` option. The default text analyzer is
720
+ `standard`; users can choose any nonempty combination of `english`, `japanese`,
721
+ `korean`, and `standard`. The sorted, deduplicated list is part of the pinned
722
+ preset/configuration hash and configures both `searchText` and managed
723
+ `embeddingText`. Discovery requires the matching schema; a different selection
724
+ uses a different Collection. Analyzer selection does not change embedding input
725
+ text or the programming-language chunker. No analyzer is a proven universal
726
+ code-search ranking solution. An initial enrichment
548
727
  candidate preserves original identifiers while adding camelCase/snake_case terms;
549
728
  pin and evaluate that transformation before adopting it as the preset.
550
729
 
551
- An embedding-enabled preset adds an unmanaged `embedding` vector field with a
552
- concrete model-selected dimension and similarity metric, fixed before Collection
553
- creation. An indexed vector field does not require a vector on every chunk; file
554
- and manifest records also omit it. The `none` preset omits the vector index entirely.
730
+ The opt-in managed presets add indexed text `embeddingText` and a managed
731
+ `embedding` vector field with provider `openai`: `text-embedding-3-small` uses
732
+ 1536 dimensions and `text-embedding-3-large` uses 3072, both with cosine similarity.
733
+ The source field, dimensions and similarity are nested under the vector field's `embedding` configuration; there are no
734
+ top-level dimension/similarity properties. Collection discovery verifies the
735
+ complete resolved schema and pinned preset. Missing `embeddingText` on skipped
736
+ chunks, files and manifests means no vector is generated for those records. The `none` preset omits the vector index entirely.
555
737
  Changing presets creates a separate index; do not silently mutate an existing
556
738
  serving index. Do not write placeholder or test vectors into a real corpus.
557
739
 
@@ -593,21 +775,54 @@ must include stored-only source round-trip and mixed record kinds.
593
775
  ## 8. File policy, chunking, and embedding reuse
594
776
 
595
777
  Every Git tree entry must be accounted for. Include source, tests, documents,
596
- configuration, build definitions, and unknown readable text by default. Maintain
597
- explicit versioned rules for binaries, generated output, and vendored dependencies;
598
- do not treat working-tree ignore rules as a complete policy. Lockfiles are included
599
- unless an explicit generated/size rule excludes them.
778
+ configuration, build definitions, and unknown readable text by default, subject to
779
+ the versioned file-purpose policy. The preset pins `filePolicy: { version: 1, rules }`
780
+ and its ordered repository-relative path rules. File selection and embedding
781
+ eligibility are separate: source/lexical retrieval can remain available without a
782
+ vector. Do not treat working-tree ignore rules as a complete policy.
783
+
784
+ Credential filenames/directories, key/certificate payloads, image/binary assets
785
+ and PEM private-key headers are hard exclusions, including for tracked files.
786
+ Credential template suffixes (`.example`, `.sample`, `.template`) remain eligible.
787
+ This is a targeted policy, not comprehensive secret detection. Dependencies,
788
+ virtual environments, build/cache outputs, minified assets/maps and logs are
789
+ excluded by default. Lockfiles, legal/author files, tabular/JSONL data, snapshots,
790
+ and generated code (common suffixes or explicit generated/do-not-edit comments in the first 8 KiB) are
791
+ lexical-only by default. Tests, ordinary docs, manifests and build/CI config remain
792
+ eligible. Embedded license headers are not removed from source chunks.
793
+
794
+ For Java files in `src/<source-set>/java/`, package components named `build`,
795
+ `dist`, `target`, or `coverage` do not imply build output. Those directory names
796
+ still exclude trees above the source root; dependency/cache directories retain
797
+ their exclusions throughout. The source policy revision is part of preset identity.
798
+
799
+ `--file-policy` accepts JSON on registration and local path dry runs. Last matching
800
+ rule wins (`exclude`, `lexical`, `semantic`); rules use case-sensitive relative
801
+ paths, `*`, `?` and whole-segment `**`. Rules can override default purpose decisions,
802
+ but never hard content/path/size/encoding exclusions. The resolved policy is stored
803
+ in the preset, not reread from a mutable checkout on import. `.gitattributes` is
804
+ not interpreted. Inventory `retrieval`/`policyReason` and chunk skip reasons expose
805
+ the decision. Changing rules changes configHash and cannot reuse a prior baseline.
806
+
807
+ Evaluation labels require explicit exclusion independently of product defaults.
808
+ Both checkout source evaluation harnesses pin `eval/source-corpus-policy.json`
809
+ (excluding `eval/**`) and fingerprint it. New runs use new artifact roots; retained
810
+ results and their old corpus/runtime identities remain historical evidence.
600
811
 
601
812
  | Special entry | Initial handling |
602
813
  | --- | --- |
603
814
  | Submodule | Record gitlink OID/path; no recursive import |
604
815
  | LFS pointer | Record metadata; no payload download or pointer indexing |
816
+ | Image asset | Exclude known image extensions case-insensitively before chunking or embedding, including text SVG and portable pixel maps; retain inventory reason `image-extension` |
605
817
  | Symlink | Record target bytes; never follow or index as source |
606
818
  | Oversized file | Exclude with actual bytes and configured limit |
607
819
  | Invalid UTF-8 content/path | Record a diagnostic and lossless path identity; do not decode lossily |
608
820
  | Empty text file | File record, zero chunks |
609
821
  | Unsupported language or parse failure | Include bounded fallback chunks and distinguish the reason |
610
822
 
823
+ Inline SVG markup in actual source files (for example, TSX components) remains
824
+ source. The image exclusion policy participates in the immutable preset identity.
825
+
611
826
  Preserve raw UTF-8 bytes, BOM, CRLF, case, Unicode, and final newlines. Byte ranges
612
827
  are authoritative `[startByte, endByte)`; display lines are one-based/inclusive.
613
828
  JavaScript UTF-16 offsets must be converted explicitly. Preserve unusual Git paths
@@ -645,6 +860,25 @@ is not an unconditional one-function-per-chunk rule.
645
860
 
646
861
  ### Initial boundary and size rules
647
862
 
863
+ The implementation adds Python/Go/Rust/C/C++ using the existing pinned WASM
864
+ grammars and Shell/SQL using bundled, checksum-pinned grammars (see
865
+ `runtime/grammars/README.md`).
866
+ Python splits top-level declarations and class bodies, keeps decorators with their
867
+ function/class, and records nested class scopes. Go keeps functions/methods,
868
+ extracts receiver type scopes, and separates named types in grouped declarations.
869
+ Rust splits `impl`, `trait` and inline module bodies, retaining generic type/trait
870
+ scopes and outer attributes/doc comments with each declaration. Macros and `cfg`
871
+ conditions remain authored source; there is no compiler expansion or evaluation.
872
+ C/C++ walks declarators and namespace/class bodies, preserving templates and both
873
+ preprocessor branches without evaluating conditions. `.h` uses C; C++ header
874
+ extensions use C++. Shell covers `.sh`/`.bash` with the Bash grammar, keeping
875
+ functions and compound commands intact. SQL keeps each top-level statement,
876
+ including CTEs and supported quoted bodies, and records created object/schema
877
+ names. Unknown dialect syntax uses whole-file parse fallback.
878
+ Functions and SQL statements larger than the token ceiling use the common bounded text splitter with
879
+ their symbol/scope preserved; nested functions stay in the containing function.
880
+ These rules do not change Java/TypeScript/JavaScript boundaries.
881
+
648
882
  Prefer functions/methods and split large nodes along internal statement boundaries.
649
883
  Cover class headers, imports, types, fields, constants, top-level code, comments,
650
884
  punctuation, and gaps. Merge small adjacent units only within one scope and budget.
@@ -724,7 +958,7 @@ structural fragments, rather than build a complex value classifier.
724
958
  | Documentation, explanatory comments/docstrings | Embed; keep attached explanations with their code where practical |
725
959
  | Meaningful type/configuration declarations | Embed initially, then evaluate |
726
960
  | Imports-only or whitespace/punctuation-only fragments | Skip with a recorded reason |
727
- | Repeated license headers and mechanical listings | Candidates for explicit, versioned skip rules after evaluation |
961
+ | Lexical-only file categories or rules | Keep exact source/chunks, omit embedding inputs and record the file policy reason; embedded license comments in authored code are not stripped |
728
962
  | Parser fallback | Do not exclude solely because parsing failed; apply content policy |
729
963
 
730
964
  Skipped chunks remain in inventory and source coverage. Retain lexical search text
@@ -740,13 +974,46 @@ choice and the finer skip rules remain evaluation decisions, not measured result
740
974
 
741
975
  ### Embedding reuse
742
976
 
743
- Cache embeddings by the exact full input and provider/model/revision/dimensions/
744
- preprocessing settings. Do not include commit, line numbers, file IDs, or build IDs
745
- in that input. A line shift can update positions while reusing the same vector;
746
- changed chunk boundaries or a renamed path in the input can legitimately miss.
747
- Cache only successful validated outputs atomically. Query embeddings use the same
748
- compatible contract and have their own cache/budget accounting. Provider aliases
749
- may drift if no immutable model revision exists; record that limitation.
977
+ The managed implementation reuses unchanged records from the immutable baseline:
978
+ compare all submitted payload fields after separately validating and removing only
979
+ the server-generated vector. Do not upload those unchanged records again. Direct
980
+ managed vector writes are forbidden, including copies fetched from an old Tag.
981
+ Changed files receive new chunk IDs and may require re-embedding even if some text
982
+ is identical. Replaying an uncertain write may also incur embedding usage. There
983
+ is no srcx-managed document or query vector cache and no promised server cache.
984
+ The older local cache remains only for internal client-embedder fixtures.
985
+
986
+ The input includes path/symbol context and source text, not commit/line/build IDs.
987
+ The preset pins provider/model/dimensions/similarity and input policy, but the
988
+ provider model name is not an immutable model revision. Validation proves vector
989
+ shape and payload integrity, not deterministic numerical reproduction by OpenAI.
990
+
991
+ Search remains lexical by default. Explicit `--mode semantic` uses managed
992
+ `knn.queryText`; `--mode hybrid` combines the existing lexical query and that kNN
993
+ query using LambdaDB RRF. Both legs enforce `kind=chunk` and the same optional
994
+ path/language filters; kNN uses a prefilter and `k=limit`, or `k=candidates`
995
+ when optional reranking requests a wider pool. The lexical leg keeps
996
+ nonembedded chunks eligible. Query/fetch/list request vectors explicitly so the
997
+ same validation applies to pinned result handles. When a deployment omits managed
998
+ vectors from list responses, fetch the affected IDs from that same immutable Tag
999
+ and require identical non-vector payloads before vector validation. Source reads still use the
1000
+ original file bytes, never enriched text. Bounded retrieval and reranking results
1001
+ are recorded in [VALIDATION.md](VALIDATION.md); they do not establish a universal
1002
+ winner or authorize default changes.
1003
+
1004
+ Optional `--rerank qwen` scores complete verified chunk bytes with a pinned local
1005
+ Qwen3-Reranker-0.6B revision, preserves candidate identity and retrieval order on
1006
+ ties, and returns a separate reranker score. Setup is explicit, inference is
1007
+ offline, and failures do not silently fall back. Every CLI invocation loads its
1008
+ own model. See [README.md](README.md#optional-local-qwen-reranker) for limits and
1009
+ runtime setup; this path does not change stored Collections or embedding presets.
1010
+
1011
+ Managed source text and semantic/hybrid query text are sent through LambdaDB to
1012
+ OpenAI and incur embedding usage plus normal LambdaDB operations/storage. Dry-run
1013
+ and lexical queries do not request query embeddings. Use explicit opt-in and a
1014
+ bounded synthetic acceptance run before evaluating private or larger corpora.
1015
+ See [managed embeddings](https://docs.lambdadb.ai/guides/collections/managed-embeddings)
1016
+ and [hybrid query](https://docs.lambdadb.ai/guides/search/hybrid) for the API contract.
750
1017
 
751
1018
  ## 9. Candidate validation, publication, and `versions`
752
1019
 
@@ -814,10 +1081,16 @@ they do not authorize the next commit on that workspace.
814
1081
  attempt identity and verifier version. Use an ID derived from the full commit
815
1082
  OID and candidate Snapshot ID so attempts cannot overwrite another Snapshot's
816
1083
  evidence. Confirm its readback before publication.
817
- 5. Create the deterministic published Tag **from the validated candidate Tag**,
818
- not from the mutable Branch. Verify both Tags have the same Snapshot ID and
819
- matching manifest. Publication changes naming, not corpus content.
820
- 6. Update optional branch-progress/control records and return the published version.
1084
+ 5. For a first publication, create the deterministic published Tag **from the
1085
+ validated candidate Tag**, not from the mutable Branch. Verify both Tags have
1086
+ the same Snapshot ID and matching manifest. If the commit is already published,
1087
+ validate and reuse its canonical Tag; retain this writer's validated candidate
1088
+ separately when its Snapshot ID differs. Publication never overwrites a commit
1089
+ Tag with another writer's snapshot.
1090
+ 6. For a tracked Git branch, update its control record with the validated writer
1091
+ snapshot and published commit Tag, clear pending ownership, and return the
1092
+ published version. Branch selectors keep using the preceding published Tag
1093
+ until this control update succeeds.
821
1094
  A delayed bookkeeping write does not erase an already published immutable Tag.
822
1095
 
823
1096
  An empty Snapshot or incomplete candidate never becomes published. A stale Tag
@@ -827,6 +1100,33 @@ avoid repeatedly validating known stale Snapshot IDs. A payload/build defect
827
1100
  requires explicit same-build recovery, not endless polling. Publication must
828
1101
  finish before the same code Branch starts a later commit.
829
1102
 
1103
+ ### Persistent Git branch state
1104
+
1105
+ Each full `refs/heads/...` name maps to one `git-<ref-digest>` writer and one
1106
+ `branch-<full-ref-digest>` control document on main (`role=git-branch`). The control
1107
+ record holds the last applied immutable baseline, canonical published Tag name,
1108
+ and pending attempt/build/commit identity. Record pending ownership before branch
1109
+ creation or corpus writes. A missing local journal cannot authorize a second
1110
+ import over pending remote state, even if the committed head still matches the
1111
+ old baseline. Only the same journal may resume; automatic abandoned-attempt
1112
+ recovery remains unimplemented.
1113
+
1114
+ Compare the writer head with the recorded baseline snapshot before the next
1115
+ import, then reconcile old IDs and hashes through its immutable Tag. This works
1116
+ without the prior local artifact and supports a branch moving backward or across
1117
+ history. Every target commit still comes from one full committed Git tree.
1118
+
1119
+ An already published commit does not skip updating a different tracked branch.
1120
+ Validate that branch's own candidate, reuse the existing canonical commit Tag,
1121
+ and retain the candidate as the writer's exact baseline when the snapshot IDs
1122
+ differ. Never overwrite the canonical commit publication with another writer's
1123
+ snapshot. This also applies when a branch returns to a previously indexed commit.
1124
+
1125
+ Branch search/resolve/read selects the last published Tag from the control record,
1126
+ including while the next import is pending. This promises the last indexed state,
1127
+ not the current Git tip. A first pending import has no searchable branch version.
1128
+ An ambiguous tracked branch/Git tag short name requires an explicit heads/tags ref.
1129
+
830
1130
  ### `versions` reads LambdaDB
831
1131
 
832
1132
  1. Resolve the repository Collection through remote metadata.
@@ -853,6 +1153,23 @@ name/Snapshot/manifest before retrying. Existing valid publication is reused.
853
1153
  A crash after candidate validation but before publication can be recovered by
854
1154
  revalidating that candidate and publishing; a `try-*` name alone is never enough.
855
1155
 
1156
+ Within one invocation, reuse the successful complete candidate check instead of
1157
+ immediately scanning it twice. Before publication, require that the candidate Tag
1158
+ still points to the Snapshot returned when it was created. This result exists
1159
+ only in memory: resuming a publication-stage journal performs full candidate
1160
+ validation again and verifies the Tag/Snapshot identity. The final Tag is still
1161
+ created from the candidate Tag, with the existing Snapshot equality check.
1162
+
1163
+ These optimizations retain full Git enumeration, local artifact copying and
1164
+ validation, full inventory construction, and at least one complete remote
1165
+ candidate verification. Cold recovery also lists the old remote baseline.
1166
+ Achieving remote validation proportional to a delta requires a verified backend
1167
+ contract tying a candidate Snapshot to the exact validated baseline plus all
1168
+ acknowledged upserts/deletes, preserving all other records and establishing index
1169
+ and managed-embedding readiness. No such contract is assumed by this importer;
1170
+ marker visibility, matching counts and changed-document sampling cannot replace
1171
+ the complete comparison. Dependency ingestion remains outside this workflow.
1172
+
856
1173
  ## 10. Git tags, exact version selection, and recovery
857
1174
 
858
1175
  ### Git release Alias synchronization
@@ -971,7 +1288,7 @@ Required meaningful checks:
971
1288
  - Byte coverage, Unicode/BOM/CRLF/trailing-newline/long-line spans are exact.
972
1289
  - Parse failures and huge nodes stay bounded and visible in reports.
973
1290
  - B contains additions/replacements/deletions while A reads remain unchanged.
974
- - A controlled line-shift fixture updates positions and reuses identical embeddings.
1291
+ - A controlled line-shift fixture updates positions; managed imports may re-embed changed IDs, while the internal client-cache fixture verifies input-based reuse.
975
1292
  - Different paths remain distinct even with identical bytes; reuse follows input.
976
1293
  - Fixed-config mismatches fail before writes; fake vectors never enter a real corpus.
977
1294
  - Explicit obsolete-ID deletion preserves replacement IDs and removes surplus chunks.
@@ -999,15 +1316,18 @@ latency, and operational cost are separate measurements.
999
1316
 
1000
1317
  ## 12. Remaining decisions and inspected evidence
1001
1318
 
1319
+ The initial parser/tokenizer presets, managed embedding choices and CLI retrieval
1320
+ modes are implemented and have bounded evaluation records. The following are
1321
+ future decisions or per-run requirements, not blockers awaiting initial design:
1322
+
1002
1323
  | Decision | When needed |
1003
1324
  | --- | --- |
1004
- | First real repositories and parser priority | Real-repository evaluation; defaults do not block fixtures |
1005
- | Exact parser/tokenizer/preset versions, enrichment and embedding skip rules | Bootstrap and retrieval evaluation; pin before publishing a corpus |
1006
- | Chunk size/overlap and syntax-versus-window tradeoff | Section 8 pilot after retrieval works; current values are starting points |
1007
- | Embedding model/dimensions/provider, data destination, spending cap | Before any real source upload or paid experiment |
1008
- | LambdaDB endpoint/project and credentials | Provisioning and live fixture run |
1009
- | Authoritative Git-tag source and observed-ref freshness policy | Manual Alias synchronization |
1010
- | Concurrent multi-host writers, retention/cleanup, configuration migration | Later internal operation, outside first CLI |
1325
+ | Additional parser languages and production repositories | Onboarding source beyond the currently tested coverage |
1326
+ | Quality/latency thresholds and any default changes | After actual development-task use; before stable rollout |
1327
+ | New embedding/reranking providers or chunking policies | A concrete unmet retrieval need; Jev access remains deferred |
1328
+ | Source authorization, endpoint/project, credentials and spending limits | Before every new corpus upload or paid experiment |
1329
+ | Authoritative Git-tag source and observation freshness | Automatic synchronization or pruning |
1330
+ | Multi-host writers, retention/cleanup and configuration migration | Later internal operation, outside the first CLI |
1011
1331
 
1012
1332
  Sources and evidence used during this design discussion:
1013
1333
 
@@ -1044,13 +1364,13 @@ Sources and evidence used during this design discussion:
1044
1364
  - [Tree-sitter parsing](https://tree-sitter.github.io/tree-sitter/using-parsers/2-basic-parsing.html):
1045
1365
  source ranges and encodings; verify the selected binding during implementation.
1046
1366
 
1047
- Development checkout references identify the inspected files, not runtime
1048
- dependencies. No
1049
- application tests, source uploads, embeddings, or live LambdaDB validation have
1050
- been performed as part of writing this document.
1367
+ Development checkout references identify the files inspected during the original
1368
+ design discussion, not runtime dependencies. That design-only review did not run
1369
+ application tests, source uploads, embeddings or live LambdaDB checks. Subsequent
1370
+ implementation and validation evidence is recorded in [VALIDATION.md](VALIDATION.md).
1051
1371
 
1052
- Document validation: the revised lexical `indexConfigs` JSON, description, four
1053
- reserved metadata labels, and one optional context label passed the local built
1372
+ Historical design validation (September 25): the revised lexical `indexConfigs`
1373
+ JSON, description, four reserved metadata labels, and one optional context label passed the local built
1054
1374
  SDK's Collection-create input validator on September 25. All three JSON examples,
1055
1375
  the illustrative source span, then-local links, code fences, and whitespace also passed
1056
1376
  document checks. These checks do not establish server acceptance, marker ordering,