@functional-systems/srcx 0.1.0-dev.1

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 (52) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/CONTRIBUTING.md +54 -0
  3. package/DESIGN.md +1057 -0
  4. package/LICENSE +202 -0
  5. package/README.md +209 -0
  6. package/RELEASING.md +137 -0
  7. package/VALIDATION.md +181 -0
  8. package/dist/build.d.ts +94 -0
  9. package/dist/build.js +433 -0
  10. package/dist/build.js.map +1 -0
  11. package/dist/chunk.d.ts +30 -0
  12. package/dist/chunk.js +296 -0
  13. package/dist/chunk.js.map +1 -0
  14. package/dist/cli.d.ts +2 -0
  15. package/dist/cli.js +276 -0
  16. package/dist/cli.js.map +1 -0
  17. package/dist/common.d.ts +17 -0
  18. package/dist/common.js +74 -0
  19. package/dist/common.js.map +1 -0
  20. package/dist/git.d.ts +38 -0
  21. package/dist/git.js +224 -0
  22. package/dist/git.js.map +1 -0
  23. package/dist/publish.d.ts +60 -0
  24. package/dist/publish.js +341 -0
  25. package/dist/publish.js.map +1 -0
  26. package/dist/releases.d.ts +8 -0
  27. package/dist/releases.js +79 -0
  28. package/dist/releases.js.map +1 -0
  29. package/dist/remote.d.ts +53 -0
  30. package/dist/remote.js +136 -0
  31. package/dist/remote.js.map +1 -0
  32. package/dist/repository.d.ts +29 -0
  33. package/dist/repository.js +180 -0
  34. package/dist/repository.js.map +1 -0
  35. package/dist/search.d.ts +46 -0
  36. package/dist/search.js +181 -0
  37. package/dist/search.js.map +1 -0
  38. package/dist/settings.d.ts +10 -0
  39. package/dist/settings.js +35 -0
  40. package/dist/settings.js.map +1 -0
  41. package/package.json +58 -0
  42. package/src/build.ts +587 -0
  43. package/src/chunk.ts +328 -0
  44. package/src/cli.ts +366 -0
  45. package/src/common.ts +71 -0
  46. package/src/git.ts +286 -0
  47. package/src/publish.ts +487 -0
  48. package/src/releases.ts +108 -0
  49. package/src/remote.ts +230 -0
  50. package/src/repository.ts +306 -0
  51. package/src/search.ts +282 -0
  52. package/src/settings.ts +59 -0
package/VALIDATION.md ADDED
@@ -0,0 +1,181 @@
1
+ # Validation record
2
+
3
+ Date: 2026-09-25 (Asia/Seoul).
4
+
5
+ ## Evidence boundary
6
+
7
+ This implementation has passed local fixtures/fault injection/SDK transport checks
8
+ and a live synthetic A/B acceptance run against the user-supplied LambdaDB
9
+ connection. Only generated test source was uploaded. No production repository
10
+ source or paid embeddings were used, and no Git repository/npm package was
11
+ published. Live evidence below is limited to this small fixture; it is not a
12
+ throughput, general concurrency, or retrieval-quality benchmark.
13
+
14
+ ## Local checks
15
+
16
+ Runtime used: Node.js 24.15.0, npm 11.12.1. Dependencies are pinned in
17
+ `package-lock.json`; Tree-sitter uses WASM assets and needs no install scripts.
18
+
19
+ ```sh
20
+ npm ci --ignore-scripts
21
+ npm run typecheck
22
+ npm run check:version
23
+ npm test
24
+ npm run test:package
25
+ npm run demo
26
+ npm run format:check
27
+ ```
28
+
29
+ Result after release-tooling setup: **34 tests passed**, with no failures,
30
+ skips, or cancellations. This includes the prior 20 application checks and 14
31
+ release/versioning checks. A clean install of the exact npm tarball also passed
32
+ the CLI contract test, including loading the parser WASM assets and importing Git
33
+ source with installation scripts disabled. These release-tooling checks ran
34
+ locally; the synthetic live acceptance record below predates this setup.
35
+ The A/B demo also passed: five included files and four exclusions per version,
36
+ one addition/modification/deletion, six obsolete record IDs, two release Aliases,
37
+ and preserved A source after publishing B.
38
+
39
+ The test suite covers:
40
+
41
+ - Source byte coverage and bounded enriched tokens across Unicode, BOM, CRLF,
42
+ missing/final newlines, long lines, syntax errors, Markdown, and config text.
43
+ - Git A/B additions, modifications, deletions, unchanged-record reuse, dirty-tree
44
+ isolation, ambiguous refs, unusual paths, invalid UTF-8, oversize files,
45
+ symlinks, submodules, binary data, dependency directories, and LFS pointers.
46
+ - Credential-reference-only configuration, endpoint validation, and remote/fork
47
+ identity. Credential-free CLI dry-run runs without a connection file.
48
+ - Idempotent publication when another branch/tag spelling resolves to the same
49
+ commit; immutable manifests normalize the requested ref to its resolved OID.
50
+ - An internal injected embedding provider/cache contract, including required
51
+ provider failures. These vectors never enter the production publication path.
52
+ - Separate final-marker writes, indexed-only polling, stale and corrupted
53
+ candidate rejection, exact corpus validation, and immutable A/B evidence.
54
+ - Unknown write outcomes, explicit same-artifact retry, unpublished timeouts,
55
+ baseline mismatch, and exclusive local writer locking.
56
+ - Real CLI/SDK retry after deleting the previous published build's local artifact:
57
+ the pending build and journal still complete publication against a loopback
58
+ HTTP fixture, while retry without `--resume` remains blocked.
59
+ - Real CLI search/read select the requested commit with subcommand `--version`;
60
+ top-level `srcx --version` still prints the CLI version. Positional option
61
+ parsing prevents the global version flag from intercepting corpus selection.
62
+ - Rejection of changed commit/build identity before any remote writes.
63
+ - Two release Aliases sharing a commit, moved targets pending until imported,
64
+ pinned old reads, and no deletion inferred from absent local tags.
65
+ - Hexadecimal Git tag names taking precedence over matching commit prefixes,
66
+ including pending targets, with explicit qualified-tag and direct-version reads.
67
+ - Provisioning recovery after a lost create ACK, preserving metadata, refusing
68
+ foreign adoption, schema mismatch, and discovery with fresh local state.
69
+ - Server-added `id: keyword` schema compatibility and complete-token lexical
70
+ readiness probes (for example, `code.ts` rather than the substring `code`).
71
+ - Real SDK request serialization, explicit Branch/Tag refs, paginated immutable
72
+ document listing, ordinary upsert/delete, Tag-to-Tag copy, disabled retries,
73
+ and sanitized user-visible errors, against a local HTTP fixture.
74
+ - Canonical dev/rc/stable versions, package/lock/tag consistency, deterministic
75
+ first-parent development numbering, stale-job rejection, and same-artifact
76
+ reruns. Simulated registry delays/failures verify bounded post-write reads and
77
+ no automatic publication retry; no test writes to npm.
78
+
79
+ Release infrastructure is prepared in `.github/workflows/publish.yaml` for Node
80
+ 22/24. Local validation does not establish GitHub Actions or npm publication
81
+ success. Initial npm registration, package-specific Trusted Publisher setup, and
82
+ enabling `NPM_DEV_PUBLISH_ENABLED` remain separate release steps. See
83
+ [RELEASING.md](RELEASING.md); no npm or Homebrew release was performed in this setup.
84
+
85
+ The demo writes [.srcx/demo-report.json](.srcx/demo-report.json). That generated
86
+ report identifies the retained synthetic repository, A/B build artifacts, counts,
87
+ deleted IDs, candidate attempts, two release aliases, and source-read preservation.
88
+ Those temporary paths are run-specific and are not committed fixtures.
89
+
90
+ ## Implementation choices and remaining scope
91
+
92
+ The initial connected preset is lexical (`embedding=none`). The internal embedding
93
+ interface verifies eligibility/cache behavior only; production provider selection,
94
+ semantic/hybrid querying, pricing, and evaluation remain open. Public imports
95
+ reject a vector-enabled build to prevent fixture vectors from reaching LambdaDB.
96
+
97
+ Each import gets a fresh `work-*` Branch, with incremental reuse only from an exact
98
+ validated previous writer snapshot. Existing writers are not mutated after
99
+ publication. Persistent `git-*` tracking, automatic failed-workspace recovery,
100
+ Alias pruning, and garbage collection are not yet implemented. Failed/candidate
101
+ resources and build artifacts are retained. A single importing host is required;
102
+ the local lock is not a distributed lease.
103
+
104
+ Parsing uses the pinned packaged grammars. Unsupported/new syntax can fall back
105
+ and is recorded; no claim of complete language-version coverage is made. There is
106
+ no optimal-chunking claim. The fixed-window baseline is implemented internally;
107
+ the planned 10–20-query retrieval comparison has not been run. The in-memory test
108
+ model does not approximate Lucene ranking, distributed indexing, retention, or
109
+ compaction timing.
110
+
111
+ Canonical publication records exist on main; listings require both the remote
112
+ summary and the matching immutable Tag manifest. A candidate or a lone `ver-*`
113
+ resource is not automatically a published version. Result handles are local to a
114
+ client; fresh clients can rediscover versions and perform direct path reads.
115
+
116
+ ## Completed live acceptance run
117
+
118
+ The run finished on 2026-09-25 at 01:41:50 Asia/Seoul. Its authoritative local
119
+ record is [.srcx/live/report.json](.srcx/live/report.json). The credentials came
120
+ from the user-provided, Git-ignored `.env.local`; only the environment-variable
121
+ name is saved in connection settings.
122
+
123
+ ```sh
124
+ SRCX_LIVE_TIMEOUT_MS=300000 npm run test:live
125
+ ```
126
+
127
+ The retained Collection and endpoint are recorded in the local report.
128
+ Environment-specific connection details are omitted from this public document.
129
+
130
+ | Version | Git commit | Published Snapshot |
131
+ | ------- | ------------------------------------------ | -------------------------------------- |
132
+ | A | `5959eac35ada29beca390445fee1cd2913b6eab4` | `60efb1ac-7e7a-427c-a862-f30d1ca1f21e` |
133
+ | B | `52e5169e73303026e32f6aee7fce70a87c3d0161` | `445dcce0-f84d-4eae-bc7d-01b5b7b047d5` |
134
+
135
+ Observed checks passed:
136
+
137
+ - Authentication, remote repository provisioning/discovery, Collection context,
138
+ the server-normalized index schema, and an empty checkpoint separate from main.
139
+ - Explicit timeout without publishing; the same attempt subsequently resumed.
140
+ After ACK, a true-consistency read exposed the marker while a false-consistency
141
+ read initially did not. Publication waited for the indexed marker and validated
142
+ the immutable candidate's complete 13-record corpus and representative query.
143
+ - A lexical search followed by an exact hash-checked source read.
144
+ - Two Git tags creating separate Aliases targeting the same A Snapshot.
145
+ - Moving `v1` to unimported B reported pending; importing B and syncing retargeted
146
+ `v1` to B while `v1-copy` stayed on A.
147
+ - B additions/modifications/deletions: `newword` and `addedword` became searchable;
148
+ `oldword` and `deleteword` were absent. The saved A result still returned A's
149
+ complete original source after B was published.
150
+ - Fresh local state rediscovered both published versions and read A by path.
151
+ Actual CLI `doctor`, `versions`, and saved-result `read --full-file` also ran
152
+ successfully against the service.
153
+
154
+ The first normal 120-second wait expired before successful readiness validation.
155
+ A later retry reached a complete candidate but exposed a client-side probe bug;
156
+ that retry stayed unpublished as well. Both were resumed using the same journal
157
+ and corpus; no marker bypass or premature publication was used. These observations
158
+ are not a measurement of steady-state indexing latency.
159
+
160
+ Two live-discovered compatibility fixes were made and regression-tested:
161
+
162
+ 1. LambdaDB adds an implicit `id: keyword` index. Schema comparison now permits
163
+ precisely that built-in field while still rejecting extra/changed user fields.
164
+ 2. The standard analyzer retained `code.ts` as a complete token. A probe using the
165
+ extracted substring `code` failed despite a correct corpus. Readiness now uses
166
+ a complete surface token and validates its returned record hash.
167
+
168
+ Diagnostic snapshots are retained under [.srcx/live/](.srcx/live/), including the
169
+ indexed-marker observation, full candidate comparison, and query comparison.
170
+ The Collection currently retains four Branches, two published Tags, four candidate
171
+ Tags, and two Aliases. No automatic cleanup was performed.
172
+
173
+ Larger corpora, multiple partitions/indexes under load, concurrent writers,
174
+ retention/compaction behavior, and semantic/hybrid relevance still need separate
175
+ validation. The single-host and no-authoritative-pruning boundaries above remain.
176
+
177
+ The SDK adapter follows the installed `@functional-systems/lambdadb@0.5.1`
178
+ contract. Lexical clauses follow the official [Boolean query documentation](https://docs.lambdadb.ai/guides/search/boolean)
179
+ and [query-string documentation](https://docs.lambdadb.ai/guides/search/query-string).
180
+ Those contracts and the user's indexing-order description informed the workaround.
181
+ The live run verified its behavior for the synthetic fixture described above.
@@ -0,0 +1,94 @@
1
+ import { type Identity } from "./git.js";
2
+ import { CHUNKER } from "./chunk.js";
3
+ import { type Doc } from "./common.js";
4
+ export declare const INDEX_CONFIGS: {
5
+ readonly kind: {
6
+ readonly type: "keyword";
7
+ };
8
+ readonly path: {
9
+ readonly type: "keyword";
10
+ };
11
+ readonly language: {
12
+ readonly type: "keyword";
13
+ };
14
+ readonly fileId: {
15
+ readonly type: "keyword";
16
+ };
17
+ readonly symbol: {
18
+ readonly type: "keyword";
19
+ };
20
+ readonly searchText: {
21
+ readonly type: "text";
22
+ readonly analyzers: readonly ["standard"];
23
+ };
24
+ };
25
+ export type Preset = {
26
+ schemaVersion: 1;
27
+ chunker: typeof CHUNKER;
28
+ mode: "syntax" | "window";
29
+ maxFileBytes: number;
30
+ embedding: {
31
+ model: string;
32
+ dimensions: number;
33
+ } | null;
34
+ };
35
+ export declare const PRESET: Preset;
36
+ export type InventoryItem = {
37
+ path: string;
38
+ pathBase64: string;
39
+ oid: string;
40
+ mode: string;
41
+ bytes: number;
42
+ status: "included" | "excluded";
43
+ reason?: string;
44
+ targetBase64?: string;
45
+ fileId?: string;
46
+ chunkIds?: string[];
47
+ contentHash?: string;
48
+ parseStatus?: string;
49
+ tokens?: number;
50
+ embedded?: number;
51
+ skipped?: number;
52
+ };
53
+ export type Build = {
54
+ format: 1;
55
+ directory: string;
56
+ repoKey: string;
57
+ configHash: string;
58
+ preset: Preset;
59
+ commitOid: string;
60
+ commitTime: string;
61
+ requestedRef: string;
62
+ branchRef?: string;
63
+ buildId: string;
64
+ inventory: InventoryItem[];
65
+ recordHashes: Record<string, string>;
66
+ recordsHash: string;
67
+ inventoryHash: string;
68
+ changes: {
69
+ added: string[];
70
+ modified: string[];
71
+ deleted: string[];
72
+ unchanged: string[];
73
+ };
74
+ obsoleteIds: string[];
75
+ counts: Record<string, number>;
76
+ };
77
+ export type Embedder = {
78
+ model: string;
79
+ dimensions: number;
80
+ embed: (text: string) => Promise<number[]>;
81
+ };
82
+ export declare function records(directory: string): AsyncGenerator<Doc>;
83
+ export declare function loadBuild(directory: string): Promise<Build>;
84
+ export declare function materialize(args: {
85
+ identity: Identity;
86
+ ref: string;
87
+ output: string;
88
+ previous?: Build;
89
+ preset?: Preset;
90
+ embedder?: Embedder;
91
+ cache?: string;
92
+ }): Promise<Build>;
93
+ export declare function validateBuild(b: Build): Promise<void>;
94
+ export declare function corpusMetadata(b: Build, repoId: string, indexId: string, attemptId: string): Doc[];