@functional-systems/srcx 0.1.0-dev.23 → 0.1.0-dev.25
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.
- package/CHANGELOG.md +21 -0
- package/DESIGN.md +35 -7
- package/README.md +140 -3
- package/VALIDATION.md +134 -0
- package/dist/build.d.ts +5 -1
- package/dist/build.js +50 -25
- package/dist/build.js.map +1 -1
- package/dist/chunk.d.ts +2 -1
- package/dist/chunk.js +5 -4
- package/dist/chunk.js.map +1 -1
- package/dist/cli.js +25 -2
- package/dist/cli.js.map +1 -1
- package/dist/file-policy.d.ts +20 -0
- package/dist/file-policy.js +96 -0
- package/dist/file-policy.js.map +1 -0
- package/dist/skills.d.ts +24 -0
- package/dist/skills.js +155 -0
- package/dist/skills.js.map +1 -0
- package/package.json +5 -4
- package/runtime/grammars/README.md +26 -2
- package/runtime/grammars/tree-sitter-bash.LICENSE +21 -0
- package/runtime/grammars/tree-sitter-bash.wasm +0 -0
- package/skills/srcx-search/SKILL.md +77 -0
- package/src/build.ts +71 -33
- package/src/chunk.ts +6 -6
- package/src/cli.ts +43 -2
- package/src/file-policy.ts +157 -0
- package/src/skills.ts +205 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
- Separate file selection from embedding eligibility. Exclude credential and
|
|
6
|
+
crypto payloads, virtual environments, caches and logs; keep lockfiles, generated
|
|
7
|
+
code, snapshots, tabular data and legal/author files available lexically without
|
|
8
|
+
embedding them. Fix case-sensitive minified-asset exclusions. Add pinned
|
|
9
|
+
`--file-policy` JSON rules for registration and local previews, explicit inventory
|
|
10
|
+
reasons and evaluation corpus exclusions for `eval/**`.
|
|
11
|
+
|
|
12
|
+
- Exclude image assets, including text SVG and portable pixel maps, before
|
|
13
|
+
indexing or embedding. Match image extensions case-insensitively, preserve
|
|
14
|
+
exclusion metadata, and keep inline SVG in source files searchable. Include
|
|
15
|
+
the source policy change in preset identity.
|
|
16
|
+
|
|
17
|
+
- Fix Shell indexing crashes on Bash comparisons such as `[[ "$value" == 1 ]]`
|
|
18
|
+
by bundling a runtime-compatible, checksum-pinned Bash grammar with its license.
|
|
19
|
+
Include the grammar in preset identity and installed-package validation.
|
|
20
|
+
|
|
21
|
+
- Bundle the srcx-search agent skill in npm and add `skills install`, `update`,
|
|
22
|
+
`remove` and `status` for Codex and Claude Code, with user/project scopes,
|
|
23
|
+
explicit setup and preservation of customized or unowned files. Removing an
|
|
24
|
+
absent skill stays read-only even when its parent directory already exists.
|
|
25
|
+
|
|
5
26
|
- Explain source-language query selection in README and search help, including
|
|
6
27
|
agent translation of query intent while preserving exact identifiers and
|
|
7
28
|
answering in the user's language. Keep multilingual input accepted without
|
package/DESIGN.md
CHANGED
|
@@ -612,21 +612,49 @@ must include stored-only source round-trip and mixed record kinds.
|
|
|
612
612
|
## 8. File policy, chunking, and embedding reuse
|
|
613
613
|
|
|
614
614
|
Every Git tree entry must be accounted for. Include source, tests, documents,
|
|
615
|
-
configuration, build definitions, and unknown readable text by default
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
615
|
+
configuration, build definitions, and unknown readable text by default, subject to
|
|
616
|
+
the versioned file-purpose policy. The preset pins `filePolicy: { version: 1, rules }`
|
|
617
|
+
and its ordered repository-relative path rules. File selection and embedding
|
|
618
|
+
eligibility are separate: source/lexical retrieval can remain available without a
|
|
619
|
+
vector. Do not treat working-tree ignore rules as a complete policy.
|
|
620
|
+
|
|
621
|
+
Credential filenames/directories, key/certificate payloads, image/binary assets
|
|
622
|
+
and PEM private-key headers are hard exclusions, including for tracked files.
|
|
623
|
+
Credential template suffixes (`.example`, `.sample`, `.template`) remain eligible.
|
|
624
|
+
This is a targeted policy, not comprehensive secret detection. Dependencies,
|
|
625
|
+
virtual environments, build/cache outputs, minified assets/maps and logs are
|
|
626
|
+
excluded by default. Lockfiles, legal/author files, tabular/JSONL data, snapshots,
|
|
627
|
+
and generated code (common suffixes or explicit generated/do-not-edit comments in the first 8 KiB) are
|
|
628
|
+
lexical-only by default. Tests, ordinary docs, manifests and build/CI config remain
|
|
629
|
+
eligible. Embedded license headers are not removed from source chunks.
|
|
630
|
+
|
|
631
|
+
`--file-policy` accepts JSON on registration and local path dry runs. Last matching
|
|
632
|
+
rule wins (`exclude`, `lexical`, `semantic`); rules use case-sensitive relative
|
|
633
|
+
paths, `*`, `?` and whole-segment `**`. Rules can override default purpose decisions,
|
|
634
|
+
but never hard content/path/size/encoding exclusions. The resolved policy is stored
|
|
635
|
+
in the preset, not reread from a mutable checkout on import. `.gitattributes` is
|
|
636
|
+
not interpreted. Inventory `retrieval`/`policyReason` and chunk skip reasons expose
|
|
637
|
+
the decision. Changing rules changes configHash and cannot reuse a prior baseline.
|
|
638
|
+
|
|
639
|
+
Evaluation labels require explicit exclusion independently of product defaults.
|
|
640
|
+
Both checkout source evaluation harnesses pin `eval/source-corpus-policy.json`
|
|
641
|
+
(excluding `eval/**`) and fingerprint it. New runs use new artifact roots; retained
|
|
642
|
+
results and their old corpus/runtime identities remain historical evidence.
|
|
619
643
|
|
|
620
644
|
| Special entry | Initial handling |
|
|
621
645
|
| --- | --- |
|
|
622
646
|
| Submodule | Record gitlink OID/path; no recursive import |
|
|
623
647
|
| LFS pointer | Record metadata; no payload download or pointer indexing |
|
|
648
|
+
| Image asset | Exclude known image extensions case-insensitively before chunking or embedding, including text SVG and portable pixel maps; retain inventory reason `image-extension` |
|
|
624
649
|
| Symlink | Record target bytes; never follow or index as source |
|
|
625
650
|
| Oversized file | Exclude with actual bytes and configured limit |
|
|
626
651
|
| Invalid UTF-8 content/path | Record a diagnostic and lossless path identity; do not decode lossily |
|
|
627
652
|
| Empty text file | File record, zero chunks |
|
|
628
653
|
| Unsupported language or parse failure | Include bounded fallback chunks and distinguish the reason |
|
|
629
654
|
|
|
655
|
+
Inline SVG markup in actual source files (for example, TSX components) remains
|
|
656
|
+
source. The image exclusion policy participates in the immutable preset identity.
|
|
657
|
+
|
|
630
658
|
Preserve raw UTF-8 bytes, BOM, CRLF, case, Unicode, and final newlines. Byte ranges
|
|
631
659
|
are authoritative `[startByte, endByte)`; display lines are one-based/inclusive.
|
|
632
660
|
JavaScript UTF-16 offsets must be converted explicitly. Preserve unusual Git paths
|
|
@@ -664,8 +692,8 @@ is not an unconditional one-function-per-chunk rule.
|
|
|
664
692
|
|
|
665
693
|
### Initial boundary and size rules
|
|
666
694
|
|
|
667
|
-
The implementation adds Python/Go/Rust/C/C
|
|
668
|
-
grammars and SQL using
|
|
695
|
+
The implementation adds Python/Go/Rust/C/C++ using the existing pinned WASM
|
|
696
|
+
grammars and Shell/SQL using bundled, checksum-pinned grammars (see
|
|
669
697
|
`runtime/grammars/README.md`).
|
|
670
698
|
Python splits top-level declarations and class bodies, keeps decorators with their
|
|
671
699
|
function/class, and records nested class scopes. Go keeps functions/methods,
|
|
@@ -762,7 +790,7 @@ structural fragments, rather than build a complex value classifier.
|
|
|
762
790
|
| Documentation, explanatory comments/docstrings | Embed; keep attached explanations with their code where practical |
|
|
763
791
|
| Meaningful type/configuration declarations | Embed initially, then evaluate |
|
|
764
792
|
| Imports-only or whitespace/punctuation-only fragments | Skip with a recorded reason |
|
|
765
|
-
|
|
|
793
|
+
| 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 |
|
|
766
794
|
| Parser fallback | Do not exclude solely because parsing failed; apply content policy |
|
|
767
795
|
|
|
768
796
|
Skipped chunks remain in inventory and source coverage. Retain lexical search text
|
package/README.md
CHANGED
|
@@ -19,6 +19,82 @@ srcx --version
|
|
|
19
19
|
srcx --help
|
|
20
20
|
```
|
|
21
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
|
+
|
|
22
98
|
## Run locally
|
|
23
99
|
|
|
24
100
|
Requires Node.js 22.14+ and Git. The default preset uses lexical search with
|
|
@@ -66,9 +142,60 @@ Each artifact contains `build.json` (inventory, configuration, counts, hashes,
|
|
|
66
142
|
change/deletion plan) and `records.jsonl` (exact file records and retrieval chunks).
|
|
67
143
|
Artifacts contain source code; keep them with the same access policy as the repo.
|
|
68
144
|
Every tree entry is accounted for, including explicit exclusions for symlinks,
|
|
69
|
-
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,
|
|
70
146
|
invalid UTF-8 paths, and files above 1 MiB. Excluded paths are preserved losslessly
|
|
71
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.
|
|
72
199
|
|
|
73
200
|
Java, TypeScript/TSX, JavaScript/JSX, Python, Go, Rust, C/C++, Shell and SQL use
|
|
74
201
|
pinned Tree-sitter WASM grammars.
|
|
@@ -85,8 +212,8 @@ pinned Tree-sitter WASM grammars.
|
|
|
85
212
|
|
|
86
213
|
`.h` files use the C grammar deterministically; C++ headers should use a listed
|
|
87
214
|
C++ extension for syntax chunking. Shell does not infer extensionless scripts from
|
|
88
|
-
shebangs or claim Zsh/Fish/PowerShell support. SQL
|
|
89
|
-
[grammar
|
|
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
|
|
90
217
|
by that grammar falls back to text. SQL strings and supported dollar-quoted bodies
|
|
91
218
|
are parsed as part of their containing statement, not split at each semicolon.
|
|
92
219
|
Rust macros/`cfg` and C/C++ preprocessor conditions are not expanded or evaluated;
|
|
@@ -264,6 +391,16 @@ For practical search → read → change-planning examples, see the
|
|
|
264
391
|
It follows three maintenance investigations through related source and tests,
|
|
265
392
|
including the limitations of previews and optional reranking.
|
|
266
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
|
+
|
|
267
404
|
## Query language and agent use
|
|
268
405
|
|
|
269
406
|
Queries can use any language; the CLI does not translate them. For lexical search,
|
package/VALIDATION.md
CHANGED
|
@@ -1,5 +1,139 @@
|
|
|
1
1
|
# Validation record
|
|
2
2
|
|
|
3
|
+
## File selection and embedding policy
|
|
4
|
+
|
|
5
|
+
Offline validation on Node 24.15.0 passed 128 tests and seven installed-package
|
|
6
|
+
checks, plus typecheck, version and formatting checks. Synthetic tracked files
|
|
7
|
+
verify credential/crypto/image exclusions, case-insensitive minified assets,
|
|
8
|
+
virtual environments, dependency/cache paths and logs. Lockfiles, generated code,
|
|
9
|
+
snapshots and data retain source and lexical chunks without managed inputs.
|
|
10
|
+
Ordinary source, tests, manifests, templates and configurable Sphinx documentation
|
|
11
|
+
remain eligible. Ordered path overrides, configuration identity, baseline rejection,
|
|
12
|
+
unchanged-file reuse, managed publication and CLI override rejection are covered.
|
|
13
|
+
The CLI evaluator's actual offline prepare test includes an in-tree answer fixture
|
|
14
|
+
and verifies it is absent from the prepared corpus.
|
|
15
|
+
|
|
16
|
+
Fresh offline inventories reused the audited source commits:
|
|
17
|
+
|
|
18
|
+
| Repository | Result |
|
|
19
|
+
| ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
20
|
+
| Requests `611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60` | Excludes 12 certificate/key payload files. Estimated managed input decreases from the image-only build's 179,548 to 159,849 tokens; legal/author files stay lexical-only and docs/conf.py stays eligible. |
|
|
21
|
+
| srcx `e83134b44a11d78a79c5941c0e1f907383f238b3` | Explicit `eval/**` exclusion removes 45 evaluation files: total chunk tokens decrease from 316,889 to 202,835. This is a corpus boundary, not a claim that earlier answers used leaked labels. |
|
|
22
|
+
| lambdadb-cli `513af6e4d262edd380013c86d51a20aad16274d7` | Retains all 38 files and 200 chunks; package-lock.json (22,076 chunk tokens), LICENSE and JSONL examples have no managed input. The retained baseline was lexical-only, so this is not a measured embedding-cost reduction. |
|
|
23
|
+
|
|
24
|
+
All excluded paths have zero file/chunk records and all lexical-only files have
|
|
25
|
+
zero embedding inputs in these rebuilt artifacts. No service writes, provider calls
|
|
26
|
+
or agent sessions were performed. Existing remote Collections and historical
|
|
27
|
+
results are unchanged. The pinned policy selects a new configuration; no legacy
|
|
28
|
+
preset compatibility or migration layer was added. Generated detection is limited
|
|
29
|
+
to explicit markers/suffixes, `.gitattributes` is not interpreted, and credential
|
|
30
|
+
rules are not a general secret scanner. Additional evaluation-label locations must
|
|
31
|
+
be added to the explicit evaluation policy before running a different suite.
|
|
32
|
+
|
|
33
|
+
## Image exclusion
|
|
34
|
+
|
|
35
|
+
Image assets are excluded by case-insensitive extension before source records,
|
|
36
|
+
chunking or embedding, including SVG and text pixel maps. Source and installed
|
|
37
|
+
CLI checks cover image exclusion for lexical and managed presets; TSX containing
|
|
38
|
+
inline SVG still produces managed chunks. The regression fails against the
|
|
39
|
+
archived pre-fix runtime. All 125 tests, six installed-package checks, typecheck,
|
|
40
|
+
version and formatting checks passed on Node 24.15.0.
|
|
41
|
+
|
|
42
|
+
A credential-free rebuild of the same Requests commit used in the semantic pilot
|
|
43
|
+
excluded the logo SVG: managed input fell from 806,268 to 179,548 estimated tokens
|
|
44
|
+
(77.7%), and managed chunks from 1,864 to 1,081. No remote import, agent rerun or
|
|
45
|
+
retrieval improvement was measured. Previous results and their runtime are retained.
|
|
46
|
+
|
|
47
|
+
## Semantic agent investigation
|
|
48
|
+
|
|
49
|
+
[The semantic follow-up](eval/SEMANTIC-AGENT-RESULTS.md) covers twelve fresh sessions
|
|
50
|
+
on four frozen Requests questions, with the same local checkout in all conditions.
|
|
51
|
+
All answers covered the required facts under assistant source review. Mean times
|
|
52
|
+
were 69.9 seconds for local tools, 68.6 for lexical-first and 68.0 for semantic-first;
|
|
53
|
+
these single-run differences do not establish an efficiency gain. Semantic used
|
|
54
|
+
more total model input than both other conditions. All srcx sessions used one
|
|
55
|
+
search followed by local reads.
|
|
56
|
+
|
|
57
|
+
All 35 task previews and five separate diagnostic previews matched pinned source
|
|
58
|
+
and immutable version metadata; twelve checkouts and 26 runtime/harness fingerprints
|
|
59
|
+
passed verification. Payload validation does not establish nearest-neighbor recall:
|
|
60
|
+
one unfiltered semantic query returned SVG chunks, while a Python-filtered query
|
|
61
|
+
returned relevant methods with higher scores. The report preserves this unresolved
|
|
62
|
+
retrieval discrepancy separately from the original agent comparison. No product
|
|
63
|
+
search policy, embedding model or ranking default changed.
|
|
64
|
+
|
|
65
|
+
## Agent workflow diagnostic
|
|
66
|
+
|
|
67
|
+
[The agent workflow record](eval/AGENT-WORKFLOW-PILOT.md) covers eight fresh Codex
|
|
68
|
+
sessions on three frozen questions against pinned public srcx/lambdadb-cli source.
|
|
69
|
+
Optional srcx access was unused in all three paired development environments.
|
|
70
|
+
A separate explicit-invocation confirmation used three searches and seven reads
|
|
71
|
+
without cloning. Both it and the Git/local baseline answered correctly under
|
|
72
|
+
assistant source review; srcx took 94.2 seconds versus 65.8, with more total model
|
|
73
|
+
input but less uncached input. No token-cost, latency or accuracy win is claimed.
|
|
74
|
+
Six successful reads and ten search previews matched pinned source/version data.
|
|
75
|
+
The report separates preparation cost, guided invocation, evolving environment
|
|
76
|
+
conditions and the audited wrapper reservation defect from product correctness.
|
|
77
|
+
|
|
78
|
+
## Bash grammar runtime compatibility
|
|
79
|
+
|
|
80
|
+
Preparing the agent workflow pilot exposed a real import failure in the public
|
|
81
|
+
`lambdadb-cli` repository at `513af6e4d262edd380013c86d51a20aad16274d7`:
|
|
82
|
+
`scripts/test-homebrew.sh` aborted local materialization with
|
|
83
|
+
`TypeError: resolved is not a function`. A minimal `[[ "$value" == 1 ]]`
|
|
84
|
+
comparison reproduces it with the previous Bash grammar/runtime combination.
|
|
85
|
+
The replacement grammar is bundled with its license and pinned checksum in
|
|
86
|
+
`CHUNKER.shellGrammar`; other language runtimes remain unchanged.
|
|
87
|
+
|
|
88
|
+
The regression fixture fails before the replacement and passes afterward,
|
|
89
|
+
preserving complete source-byte coverage and syntax spans. The same fixture is
|
|
90
|
+
included in installed-package import checks. On Node 24.15.0, all 124 tests,
|
|
91
|
+
six installed-package tests, formatting/version checks and typecheck passed.
|
|
92
|
+
The two public pilot corpora also passed local materialization after the fix:
|
|
93
|
+
139 files/928 chunks for srcx and 38 files/200 chunks for lambdadb-cli, with no
|
|
94
|
+
embeddings. These checks establish indexing/packaging correctness, not an agent
|
|
95
|
+
accuracy or efficiency improvement.
|
|
96
|
+
|
|
97
|
+
## Agent skill installation
|
|
98
|
+
|
|
99
|
+
The npm artifact includes `skills/srcx-search/SKILL.md`. The `skills` command
|
|
100
|
+
installs, reports, updates and removes the bundled copy for Codex or Claude Code
|
|
101
|
+
in user/project scope. No credentials or network access are needed for those
|
|
102
|
+
operations. A content-hash/package-version footer distinguishes unchanged managed
|
|
103
|
+
copies from custom files; modified/unowned content, extra files and symlinked
|
|
104
|
+
managed paths are preserved. Scope selection does not edit unrelated agent
|
|
105
|
+
settings or infer a project root.
|
|
106
|
+
|
|
107
|
+
On Node 24.15.0, formatting/version checks, typecheck, all 124 tests and six packed
|
|
108
|
+
CLI tests passed. Lifecycle tests cover both agents and scopes using isolated
|
|
109
|
+
roots, replacement of a previous managed bundle, custom-file preservation,
|
|
110
|
+
symlinks, active locks, invalid options and no-write status/absent removal. Absent
|
|
111
|
+
removal also covers existing read-only parent directories for both agents/scopes
|
|
112
|
+
and preserves a pre-existing lock without acquiring it. The permission regression
|
|
113
|
+
tests fail before the fix and pass afterward on the local non-root POSIX runtime;
|
|
114
|
+
those permission tests are skipped on Windows or when running as root. Packed
|
|
115
|
+
CLI tests exercise both project destinations without config, then the existing
|
|
116
|
+
loopback workflow covers skill installation, repository discovery, commit
|
|
117
|
+
resolution, search and exact source reads. This is deterministic integration
|
|
118
|
+
validation; a model does not choose the commands in those tests.
|
|
119
|
+
|
|
120
|
+
The skill-creator validator accepted the skill. Separately, a fresh npm consumer
|
|
121
|
+
installed the tarball and Codex CLI 0.157.1 `skills/list` discovered the installed
|
|
122
|
+
project skill as enabled. Removing it removed it from the actual runtime catalog;
|
|
123
|
+
reinstalling restored it with `forceReload`. This exercised the real discovery
|
|
124
|
+
path without model requests. Claude Code's documented destination and installed
|
|
125
|
+
file lifecycle are covered, but Claude runtime discovery and either agent's
|
|
126
|
+
autonomous skill selection have not been exercised. Default local paths are the
|
|
127
|
+
supported installer targets; custom config directories and cloud/account skill
|
|
128
|
+
sync are outside this installation flow.
|
|
129
|
+
|
|
130
|
+
There were no live LambdaDB changes, embedding requests, global CLI installation,
|
|
131
|
+
or changes to the developer's personal skill directories. Tests and discovery
|
|
132
|
+
used isolated directories. This validates packaging/discovery, not token savings,
|
|
133
|
+
latency improvements or ranking quality.
|
|
134
|
+
|
|
135
|
+
Date: 2026-09-26 (Asia/Seoul).
|
|
136
|
+
|
|
3
137
|
## Query-language guidance
|
|
4
138
|
|
|
5
139
|
README and search help explain source-language query selection without rejecting
|
package/dist/build.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { resolveCommit, type Identity } from "./git.js";
|
|
2
2
|
import { CHUNKER } from "./chunk.js";
|
|
3
3
|
import { type Doc } from "./common.js";
|
|
4
|
+
import { type FilePolicy } from "./file-policy.js";
|
|
4
5
|
export declare const ANALYZERS: readonly ["english", "japanese", "korean", "standard"];
|
|
5
6
|
export type Analyzer = (typeof ANALYZERS)[number];
|
|
6
7
|
export declare function normalizeAnalyzers(value: unknown): Analyzer[];
|
|
@@ -33,6 +34,7 @@ export type Preset = {
|
|
|
33
34
|
/** Internal evaluation override; the CLI keeps its original enrichment. */
|
|
34
35
|
enrichment?: "path-only-v1";
|
|
35
36
|
maxFileBytes: number;
|
|
37
|
+
filePolicy: FilePolicy;
|
|
36
38
|
embedding: {
|
|
37
39
|
model: string;
|
|
38
40
|
dimensions: number;
|
|
@@ -46,7 +48,7 @@ export declare const PRESET: Preset;
|
|
|
46
48
|
/** Embedding variants share the same chunking behavior. */
|
|
47
49
|
export declare const MANAGED_PRESET: Preset;
|
|
48
50
|
export declare const MANAGED_LARGE_PRESET: Preset;
|
|
49
|
-
export declare function presetFor(embedding?: string, analyzers?: readonly string[]): Preset;
|
|
51
|
+
export declare function presetFor(embedding?: string, analyzers?: readonly string[], filePolicy?: unknown): Preset;
|
|
50
52
|
export declare function supportedPreset(preset: unknown): preset is Preset;
|
|
51
53
|
export declare function indexConfigs(preset?: Preset): {
|
|
52
54
|
searchText: {
|
|
@@ -114,6 +116,8 @@ export type InventoryItem = {
|
|
|
114
116
|
bytes: number;
|
|
115
117
|
status: "included" | "excluded";
|
|
116
118
|
reason?: string;
|
|
119
|
+
retrieval?: "lexical" | "semantic";
|
|
120
|
+
policyReason?: string;
|
|
117
121
|
targetBase64?: string;
|
|
118
122
|
fileId?: string;
|
|
119
123
|
chunkIds?: string[];
|
package/dist/build.js
CHANGED
|
@@ -5,6 +5,7 @@ import { join, resolve } from "node:path";
|
|
|
5
5
|
import { Blobs, inventory, resolveCommit } from "./git.js";
|
|
6
6
|
import { chunk, CHUNKER, tokens } from "./chunk.js";
|
|
7
7
|
import { atomic, canonical, hash, invariant, lineAt, json, utf8, optionalJson, } from "./common.js";
|
|
8
|
+
import { FILE_POLICY, normalizeFilePolicy, hardExclusion, privateKeyContent, fileDecision, } from "./file-policy.js";
|
|
8
9
|
export const ANALYZERS = ["english", "japanese", "korean", "standard"];
|
|
9
10
|
export function normalizeAnalyzers(value) {
|
|
10
11
|
invariant(Array.isArray(value) &&
|
|
@@ -26,6 +27,7 @@ export const PRESET = {
|
|
|
26
27
|
chunker: CHUNKER,
|
|
27
28
|
mode: "syntax",
|
|
28
29
|
maxFileBytes: 1024 * 1024,
|
|
30
|
+
filePolicy: FILE_POLICY,
|
|
29
31
|
embedding: null,
|
|
30
32
|
};
|
|
31
33
|
/** Embedding variants share the same chunking behavior. */
|
|
@@ -48,7 +50,7 @@ export const MANAGED_LARGE_PRESET = {
|
|
|
48
50
|
dimensions: 3072,
|
|
49
51
|
},
|
|
50
52
|
};
|
|
51
|
-
export function presetFor(embedding = "none", analyzers = PRESET.analyzers) {
|
|
53
|
+
export function presetFor(embedding = "none", analyzers = PRESET.analyzers, filePolicy = FILE_POLICY) {
|
|
52
54
|
invariant(["none", "text-embedding-3-small", "text-embedding-3-large"].includes(embedding), "Embedding must be none, text-embedding-3-small or text-embedding-3-large.");
|
|
53
55
|
const base = embedding === "none"
|
|
54
56
|
? PRESET
|
|
@@ -56,16 +58,20 @@ export function presetFor(embedding = "none", analyzers = PRESET.analyzers) {
|
|
|
56
58
|
? MANAGED_LARGE_PRESET
|
|
57
59
|
: MANAGED_PRESET;
|
|
58
60
|
const normalized = normalizeAnalyzers(analyzers);
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
const configured = {
|
|
62
|
+
...base,
|
|
63
|
+
analyzers: normalized,
|
|
64
|
+
filePolicy: normalizeFilePolicy(filePolicy),
|
|
65
|
+
};
|
|
66
|
+
return hash(configured) === hash(base) ? base : configured;
|
|
62
67
|
}
|
|
63
68
|
export function supportedPreset(preset) {
|
|
64
69
|
if (!preset || typeof preset !== "object" || Array.isArray(preset))
|
|
65
70
|
return false;
|
|
66
71
|
try {
|
|
67
72
|
const analyzers = normalizeAnalyzers(preset.analyzers);
|
|
68
|
-
|
|
73
|
+
const filePolicy = normalizeFilePolicy(preset.filePolicy);
|
|
74
|
+
return [PRESET, MANAGED_PRESET, MANAGED_LARGE_PRESET].some((base) => hash({ ...base, analyzers, filePolicy }) === hash(preset));
|
|
69
75
|
}
|
|
70
76
|
catch {
|
|
71
77
|
return false;
|
|
@@ -123,18 +129,10 @@ export async function loadBuild(directory) {
|
|
|
123
129
|
b.directory = resolve(directory);
|
|
124
130
|
return b;
|
|
125
131
|
}
|
|
126
|
-
function exclude(path) {
|
|
127
|
-
if (/(^|\/)(node_modules|vendor|vendored|dist|build|target|coverage|\.git|\.next)(\/|$)/.test(path))
|
|
128
|
-
return "dependency-or-build-output";
|
|
129
|
-
if (/\.(png|jpe?g|gif|ico|pdf|zip|gz|jar|class|woff2?|mp[34]|exe|dll|so|dylib|wasm)$/i.test(path))
|
|
130
|
-
return "binary-extension";
|
|
131
|
-
if (/\.(min\.(js|css)|map)$/.test(path))
|
|
132
|
-
return "generated-output";
|
|
133
|
-
return undefined;
|
|
134
|
-
}
|
|
135
132
|
export async function materialize(args) {
|
|
136
133
|
const preset = args.preset ?? PRESET, configHash = hash(preset), prev = args.previous;
|
|
137
|
-
invariant(hash(preset.
|
|
134
|
+
invariant(hash(preset.filePolicy) === hash(normalizeFilePolicy(preset.filePolicy)) &&
|
|
135
|
+
hash(preset.analyzers) === hash(normalizeAnalyzers(preset.analyzers)) &&
|
|
138
136
|
hash(preset.chunker) === hash(CHUNKER) &&
|
|
139
137
|
["syntax", "window"].includes(preset.mode) &&
|
|
140
138
|
(preset.enrichment === undefined ||
|
|
@@ -194,7 +192,9 @@ export async function materialize(args) {
|
|
|
194
192
|
item.targetBase64 = (await blobs.read(e)).toString("base64");
|
|
195
193
|
continue;
|
|
196
194
|
}
|
|
197
|
-
const
|
|
195
|
+
const pathDecision = fileDecision(e.path, preset.filePolicy);
|
|
196
|
+
const reason = hardExclusion(e.path) ??
|
|
197
|
+
(pathDecision.action === "exclude" ? pathDecision.reason : undefined);
|
|
198
198
|
if (reason) {
|
|
199
199
|
item.reason = reason;
|
|
200
200
|
continue;
|
|
@@ -224,6 +224,11 @@ export async function materialize(args) {
|
|
|
224
224
|
item.reason = "lfs-pointer";
|
|
225
225
|
continue;
|
|
226
226
|
}
|
|
227
|
+
if (privateKeyContent(source)) {
|
|
228
|
+
item.reason = "private-key-content";
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
const decision = fileDecision(e.path, preset.filePolicy, source);
|
|
227
232
|
const parsed = await chunk(source, e.path, preset.mode, preset.enrichment);
|
|
228
233
|
const contentHash = hash(data);
|
|
229
234
|
const fileId = `f-${hash([e.pathBase64, contentHash])}`;
|
|
@@ -247,6 +252,8 @@ export async function materialize(args) {
|
|
|
247
252
|
}
|
|
248
253
|
Object.assign(item, {
|
|
249
254
|
status: "included",
|
|
255
|
+
retrieval: decision.action,
|
|
256
|
+
policyReason: decision.reason,
|
|
250
257
|
contentHash,
|
|
251
258
|
fileId,
|
|
252
259
|
chunkIds: [],
|
|
@@ -273,7 +280,8 @@ export async function materialize(args) {
|
|
|
273
280
|
? "structural-only"
|
|
274
281
|
: "embedding-disabled",
|
|
275
282
|
};
|
|
276
|
-
const eligible =
|
|
283
|
+
const eligible = decision.action === "semantic" &&
|
|
284
|
+
!["imports", "structural"].includes(span.chunkKind);
|
|
277
285
|
if (preset.embedding && eligible) {
|
|
278
286
|
const inputHash = hash([preset.embedding, span.searchText]);
|
|
279
287
|
if (preset.embedding.managed) {
|
|
@@ -309,9 +317,11 @@ export async function materialize(args) {
|
|
|
309
317
|
}
|
|
310
318
|
else {
|
|
311
319
|
doc.embeddingSkipReason = preset.embedding
|
|
312
|
-
?
|
|
313
|
-
?
|
|
314
|
-
: "
|
|
320
|
+
? decision.action === "lexical"
|
|
321
|
+
? decision.reason
|
|
322
|
+
: span.chunkKind === "imports"
|
|
323
|
+
? "imports-only"
|
|
324
|
+
: "structural-only"
|
|
315
325
|
: "embedding-disabled";
|
|
316
326
|
item.skipped++;
|
|
317
327
|
}
|
|
@@ -402,7 +412,10 @@ export async function validateBuild(b) {
|
|
|
402
412
|
/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(b.commitOid) &&
|
|
403
413
|
b.buildId ===
|
|
404
414
|
hash([b.repoKey, b.commitOid, b.configHash, "srcx-builder-v1"]), "Build commit identity mismatch; rebuild from the intended Git commit.");
|
|
405
|
-
invariant(hash(b.preset.
|
|
415
|
+
invariant(hash(b.preset.filePolicy) ===
|
|
416
|
+
hash(normalizeFilePolicy(b.preset.filePolicy)) &&
|
|
417
|
+
hash(b.preset.analyzers) ===
|
|
418
|
+
hash(normalizeAnalyzers(b.preset.analyzers)) &&
|
|
406
419
|
hash(b.preset) === b.configHash &&
|
|
407
420
|
hash(b.inventory) === b.inventoryHash, "Build metadata hash mismatch.");
|
|
408
421
|
const seen = new Set();
|
|
@@ -411,6 +424,7 @@ export async function validateBuild(b) {
|
|
|
411
424
|
const expectedFile = new Map(b.inventory
|
|
412
425
|
.filter((e) => e.status === "included")
|
|
413
426
|
.map((e) => [e.fileId, e]));
|
|
427
|
+
let activeDecision;
|
|
414
428
|
const completedFiles = new Set();
|
|
415
429
|
const finish = () => {
|
|
416
430
|
if (activeFile) {
|
|
@@ -435,6 +449,12 @@ export async function validateBuild(b) {
|
|
|
435
449
|
end = 0;
|
|
436
450
|
count = 0;
|
|
437
451
|
const entry = expectedFile.get(doc.id);
|
|
452
|
+
activeDecision = fileDecision(doc.path, b.preset.filePolicy, doc.sourceText);
|
|
453
|
+
invariant(!hardExclusion(doc.path) &&
|
|
454
|
+
!privateKeyContent(doc.sourceText) &&
|
|
455
|
+
activeDecision.action !== "exclude" &&
|
|
456
|
+
entry?.retrieval === activeDecision.action &&
|
|
457
|
+
entry?.policyReason === activeDecision.reason, "File policy or inventory decision mismatch.");
|
|
438
458
|
const raw = Buffer.from(doc.sourceText);
|
|
439
459
|
invariant(entry &&
|
|
440
460
|
hash(raw) === doc.contentHash &&
|
|
@@ -470,7 +490,8 @@ export async function validateBuild(b) {
|
|
|
470
490
|
doc.tokenCount === tokens(doc.searchText) &&
|
|
471
491
|
Number(doc.tokenCount) <= CHUNKER.maxTokens, "Invalid chunk source/position/token binding.");
|
|
472
492
|
if (b.preset.embedding?.managed) {
|
|
473
|
-
const eligible =
|
|
493
|
+
const eligible = activeDecision.action === "semantic" &&
|
|
494
|
+
!["imports", "structural"].includes(String(doc.chunkKind));
|
|
474
495
|
invariant(eligible
|
|
475
496
|
? doc.embeddingStatus === "managed" &&
|
|
476
497
|
doc.embeddingText === doc.searchText &&
|
|
@@ -481,12 +502,16 @@ export async function validateBuild(b) {
|
|
|
481
502
|
doc.embeddingText === undefined &&
|
|
482
503
|
doc.embeddingInputHash === undefined &&
|
|
483
504
|
doc.embeddingSkipReason ===
|
|
484
|
-
(
|
|
485
|
-
?
|
|
486
|
-
:
|
|
505
|
+
(activeDecision.action === "lexical"
|
|
506
|
+
? activeDecision.reason
|
|
507
|
+
: doc.chunkKind === "imports"
|
|
508
|
+
? "imports-only"
|
|
509
|
+
: "structural-only"), "Invalid managed embedding input or eligibility.");
|
|
487
510
|
}
|
|
488
511
|
else if (doc.embeddingStatus === "embedded")
|
|
489
512
|
invariant(b.preset.embedding &&
|
|
513
|
+
activeDecision.action === "semantic" &&
|
|
514
|
+
!["imports", "structural"].includes(String(doc.chunkKind)) &&
|
|
490
515
|
Array.isArray(doc.embedding) &&
|
|
491
516
|
doc.embedding.length === b.preset.embedding.dimensions &&
|
|
492
517
|
doc.embedding.every(Number.isFinite), "Invalid embedded chunk.");
|