dsh-gitnexus-plus 0.1.1 → 0.1.2
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/README.md +197 -49
- package/lib/bin/search-helper.d.ts +22 -0
- package/lib/bin/search-helper.d.ts.map +1 -0
- package/lib/bin/search-helper.js +57 -0
- package/lib/bin/search-helper.js.map +1 -0
- package/lib/client.js +576 -87
- package/lib/gitnexus/analyze.d.ts +27 -2
- package/lib/gitnexus/analyze.d.ts.map +1 -1
- package/lib/gitnexus/analyze.js +31 -6
- package/lib/gitnexus/analyze.js.map +1 -1
- package/lib/gitnexus/commands.d.ts +41 -8
- package/lib/gitnexus/commands.d.ts.map +1 -1
- package/lib/gitnexus/commands.js +62 -9
- package/lib/gitnexus/commands.js.map +1 -1
- package/lib/gitnexus/coverage.d.ts.map +1 -1
- package/lib/gitnexus/coverage.js +3 -1
- package/lib/gitnexus/coverage.js.map +1 -1
- package/lib/gitnexus/index-meta.d.ts +15 -5
- package/lib/gitnexus/index-meta.d.ts.map +1 -1
- package/lib/gitnexus/index-meta.js +25 -5
- package/lib/gitnexus/index-meta.js.map +1 -1
- package/lib/gitnexus/languages.d.ts +7 -0
- package/lib/gitnexus/languages.d.ts.map +1 -1
- package/lib/gitnexus/languages.js +82 -2
- package/lib/gitnexus/languages.js.map +1 -1
- package/lib/gitnexus/root.d.ts +6 -0
- package/lib/gitnexus/root.d.ts.map +1 -1
- package/lib/gitnexus/root.js +6 -0
- package/lib/gitnexus/root.js.map +1 -1
- package/lib/gitnexus/scan.d.ts +1 -0
- package/lib/gitnexus/scan.d.ts.map +1 -1
- package/lib/gitnexus/scan.js +3 -1
- package/lib/gitnexus/scan.js.map +1 -1
- package/lib/gitnexus/search.d.ts +167 -0
- package/lib/gitnexus/search.d.ts.map +1 -0
- package/lib/gitnexus/search.js +517 -0
- package/lib/gitnexus/search.js.map +1 -0
- package/lib/index.d.ts +32 -13
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +62 -21
- package/lib/index.js.map +1 -1
- package/lib/routes/analyze.d.ts +8 -2
- package/lib/routes/analyze.d.ts.map +1 -1
- package/lib/routes/analyze.js +5 -1
- package/lib/routes/analyze.js.map +1 -1
- package/lib/routes/coverage.d.ts +13 -5
- package/lib/routes/coverage.d.ts.map +1 -1
- package/lib/routes/coverage.js +24 -11
- package/lib/routes/coverage.js.map +1 -1
- package/lib/routes/search.d.ts +27 -0
- package/lib/routes/search.d.ts.map +1 -0
- package/lib/routes/search.js +77 -0
- package/lib/routes/search.js.map +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -50,7 +50,9 @@ It does **not**:
|
|
|
50
50
|
and the two stay separate;
|
|
51
51
|
- claim authorship of, or any contribution to, GitNexus. All rights in GitNexus belong
|
|
52
52
|
to its author;
|
|
53
|
-
- replace GitNexus. With no GitNexus index there is
|
|
53
|
+
- replace GitNexus. With no GitNexus index there is no graph to display — only a
|
|
54
|
+
working-tree scan (file counts, bytes, languages), which is useful but is not a
|
|
55
|
+
substitute for the graph.
|
|
54
56
|
|
|
55
57
|
## Licence — read this before a commercial use
|
|
56
58
|
|
|
@@ -99,9 +101,22 @@ GitNexus, and installing this plugin installs GitNexus.**
|
|
|
99
101
|
one is the point: of the files people are actively editing, which does the graph
|
|
100
102
|
not see?
|
|
101
103
|
- **Language distribution by bytes**, split three ways: languages GitNexus can
|
|
102
|
-
*parse* into the graph, formats it merely *recognizes*, and everything else.
|
|
104
|
+
*parse* into the graph, formats it merely *recognizes*, and everything else. When
|
|
105
|
+
GitNexus is absent, a built-in extension map keeps the breakdown useful; those
|
|
106
|
+
rows are marked `detector: "builtin"` and are never presented as *parsed*.
|
|
103
107
|
- **Resolver confidence** — untyped receiver sites, which make `impact` and
|
|
104
108
|
`context` a lower bound rather than an exact answer.
|
|
109
|
+
- **A scan-only report when there is no index** — file count, selected count, bytes
|
|
110
|
+
and language split are readable from the working tree alone. The panel shows them
|
|
111
|
+
under "尚未索引" instead of an empty state, and the initialize command sits beside
|
|
112
|
+
them.
|
|
113
|
+
- **Keyword search with click-to-open** — the panel's search box asks the graph for
|
|
114
|
+
nodes whose `name` or `filePath` contains the query, and returns the graph node
|
|
115
|
+
kind, name, path and line. **Clicking a hit opens that file in the platform's file
|
|
116
|
+
viewer at that line** through `ctx.sidebarRight.openResource` and a
|
|
117
|
+
`dsh-resource://file/session/...` address; a separate 复制 button copies
|
|
118
|
+
`path:line`. When the graph helper cannot start, the bounded source-text fallback
|
|
119
|
+
is used instead and the card is labelled 源码关键词(回退).
|
|
105
120
|
|
|
106
121
|
## Why the git three-way split matters
|
|
107
122
|
|
|
@@ -169,6 +184,20 @@ Everything runs through `ctx.shell`, so a sandboxed deployment confines it exact
|
|
|
169
184
|
confines your own commands. **A refusal is reported as a refusal and never retried
|
|
170
185
|
wider** — the plugin never asks for more scope than the session already granted.
|
|
171
186
|
|
|
187
|
+
**The installed copy is the one every later step uses.** The install prefix is resolved
|
|
188
|
+
once and passed to all three consumers: the coverage engine's own scan primitives, the
|
|
189
|
+
language detector, and the `analyze` runner. This wiring was missing in 0.1.1 — the
|
|
190
|
+
installer wrote a plugin-owned tree, while the reader and runner probed only PATH and
|
|
191
|
+
the declared dependency, so the install succeeded and *nothing used it*. A machine with
|
|
192
|
+
no global GitNexus still reported "absent" after a successful install.
|
|
193
|
+
|
|
194
|
+
**Install → initialize is one authorised step.** If the current project has no index,
|
|
195
|
+
a successful install continues with a single `gitnexus analyze --index-only` for that
|
|
196
|
+
project, so the operator gets from "no GitNexus" to a visible index without a second
|
|
197
|
+
click. The install confirmation says this before anything starts. The chain is gated on
|
|
198
|
+
the install having been started from this panel and on the project still having no
|
|
199
|
+
index; it never silently refreshes an index that already exists.
|
|
200
|
+
|
|
172
201
|
If your GitNexus lives somewhere unusual, name it directly and none of this applies:
|
|
173
202
|
|
|
174
203
|
```sh
|
|
@@ -200,23 +229,67 @@ In DSH the plugin exposes:
|
|
|
200
229
|
- **tool** `gitnexus_coverage` — `{ repo, includeLanguages? }`
|
|
201
230
|
- **route** `GET /api/gitnexus/coverage?repo=<project>` — one report, plus the
|
|
202
231
|
maintenance commands for that project
|
|
232
|
+
- **route** `GET /api/gitnexus/search?repo=<project>&q=<keyword>&limit=20` —
|
|
233
|
+
read-only keyword search over the graph's symbol names and file paths
|
|
203
234
|
- **panel** — a right-sidebar tab type `gitnexus`, opened from the sidebar's **+** →
|
|
204
235
|
guide page ("GitNexus 索引")
|
|
205
236
|
|
|
206
|
-
The coverage route is read-only
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
237
|
+
The coverage route is read-only. Its bound is a **project root** — a directory with a
|
|
238
|
+
`.gitnexus` index or a `.git` marker — so it cannot be turned into a filesystem probe.
|
|
239
|
+
An index is no longer required: a git project without one gets the engine's scan-only
|
|
240
|
+
report, which is what makes "no index yet" informative. It is additionally restricted
|
|
241
|
+
to loopback peers because a third-party DSH route is unauthenticated by default on a
|
|
242
|
+
bare `dsh web` profile.
|
|
210
243
|
|
|
211
244
|
There is now a **second** route, `/api/gitnexus/analyze`, and it is the only one that
|
|
212
|
-
can change anything. It answers `POST` to start an incremental refresh
|
|
213
|
-
where that got to, and `DELETE` to stop it. It is a separate module from the coverage
|
|
245
|
+
can change anything. It answers `POST` to start an incremental refresh (`?force=1`
|
|
246
|
+
selects a full rebuild), `GET` to report where that got to, and `DELETE` to stop it. It is a separate module from the coverage
|
|
214
247
|
route so the read-only half keeps a method policy that cannot mutate — the shared guard
|
|
215
248
|
takes the accepted methods from the route rather than hard-coding one set for both. The
|
|
216
249
|
mutating verbs additionally pass the write guard, which refuses cross-origin requests;
|
|
217
250
|
loopback alone is not enough, because any page the operator visits can reach
|
|
218
251
|
`127.0.0.1`. See **Maintenance** below for what it will and will not do.
|
|
219
252
|
|
|
253
|
+
A **third** route, `/api/gitnexus/search`, is read-only like coverage but queries the
|
|
254
|
+
LadybugDB graph instead of the manifest. It opens the database read-only and searches
|
|
255
|
+
node names and file paths; it does **not** use FTS, which is why it works on an index
|
|
256
|
+
built with `--skip-fts` and on a machine where the FTS extension fails to load. The
|
|
257
|
+
response carries the node kind, name, path and line, plus an honest warning when
|
|
258
|
+
content-level FTS is unavailable.
|
|
259
|
+
|
|
260
|
+
**Two tiers, because the host shell can be unavailable.** The normal path is the
|
|
261
|
+
graph query. If the helper cannot start — a Windows sandbox backend that cannot create
|
|
262
|
+
its own temp directory, no shell executor, a busy database — the route falls back to a
|
|
263
|
+
bounded source-text search over the files listed in the index manifest. That fallback
|
|
264
|
+
needs neither a shell nor the native addon; it returns `mode: "text"`, searches code
|
|
265
|
+
files before documentation, caps files/bytes/matches, and says so in `warning` and in
|
|
266
|
+
the panel's card title. A silent swap between "graph" and "source text" would be a
|
|
267
|
+
dishonest answer, so the mode is part of the response.
|
|
268
|
+
|
|
269
|
+
**The graph query runs in a Node helper subprocess, not in the DSH host.** The host runs on
|
|
270
|
+
Electron's Node, and GitNexus's LadybugDB addon is built for the system Node ABI.
|
|
271
|
+
Loading it in-process fails with `A dynamic link library (DLL) initialization routine
|
|
272
|
+
failed ... lbugjs.node`; the same addon loads under the system Node 24 that the CLI
|
|
273
|
+
uses. The host therefore starts:
|
|
274
|
+
|
|
275
|
+
```
|
|
276
|
+
node lib/bin/search-helper.js <repo> <keyword> <limit> <managed-prefix>
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
and parses one JSON object. That is the same execution boundary the analyze runner
|
|
280
|
+
already uses, and it keeps the panel process free of native state it cannot load.
|
|
281
|
+
Consequently the graph path needs a shell executor and `node` on the shell's PATH;
|
|
282
|
+
without them it falls back to source text, not an empty result list.
|
|
283
|
+
|
|
284
|
+
**Clicking a hit opens the file, not a copy.** The row calls
|
|
285
|
+
`ctx.sidebarRight.openResourceIn(sessionId, address, { params: { line } })` (or the
|
|
286
|
+
public `openResource` when the targeted variant is unavailable) with
|
|
287
|
+
`dsh-resource://file/session/<session>/<path>`. That is the same address and line
|
|
288
|
+
parameter the built-in file strip and the chat's file links use, so the platform's
|
|
289
|
+
own file viewer/editor handles the navigation. A separate 复制 button remains for the
|
|
290
|
+
`path:line` text. A profile without a right-sidebar controller falls back to copying
|
|
291
|
+
and says so.
|
|
292
|
+
|
|
220
293
|
## TypeScript, and why the build looks the way it does
|
|
221
294
|
|
|
222
295
|
The source is TypeScript under `strict`, including `noImplicitAny`. That is not
|
|
@@ -290,6 +363,9 @@ That is not stylistic: a component that fetches cannot be rendered against a
|
|
|
290
363
|
fixture, and the states worth asserting on — a report with skipped files, one
|
|
291
364
|
without, an error, missing language data — are exactly the ones a fixture supplies.
|
|
292
365
|
`test/client.mjs` renders each of them through a minimal single-pass hooks shim.
|
|
366
|
+
Keyword search follows the same split: `CoveragePanel` owns the request and
|
|
367
|
+
`SearchSection` is a pure function of its props, so the empty, error and result
|
|
368
|
+
states are all fixture-testable without a graph database.
|
|
293
369
|
|
|
294
370
|
Styling is theme-agnostic by construction: host elements only, `color` inherited,
|
|
295
371
|
every border derived from `currentColor`. `@deepseek-ai/dsh-client-ui-primitives` is
|
|
@@ -310,6 +386,28 @@ GET /api/gitnexus/coverage?repo=D:\Project\material-ui HTTP 200
|
|
|
310
386
|
GET /api/gitnexus/coverage?repo=C:\Windows HTTP 404 (refused)
|
|
311
387
|
```
|
|
312
388
|
|
|
389
|
+
The search engine and its route were exercised over a loopback harness against this
|
|
390
|
+
repository's real index (the same database the panel reads):
|
|
391
|
+
|
|
392
|
+
```
|
|
393
|
+
GET /api/gitnexus/search?repo=D:\Project\gitnexus-plus&q=analyzeCoverage HTTP 200
|
|
394
|
+
Function analyzeCoverage src/gitnexus/coverage.ts:507
|
|
395
|
+
GET /api/gitnexus/search?repo=D:\Project\gitnexus-plus&q=client/index&limit=3 HTTP 200
|
|
396
|
+
File index.ts src/client/index.ts
|
|
397
|
+
GET /api/gitnexus/search?repo=C:\Windows\System32&q=x HTTP 404 (refused)
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
The helper boundary itself, run under the system Node 24, returns the JSON the host
|
|
401
|
+
parses (the host's Electron Node cannot load the native addon):
|
|
402
|
+
|
|
403
|
+
```
|
|
404
|
+
node lib/bin/search-helper.js D:\Project\gitnexus-plus analyzeCoverage 5
|
|
405
|
+
{"ok":true,"report":{"query":"analyzecoverage","mode":"graph",
|
|
406
|
+
"results":[{"kind":"Function","name":"analyzeCoverage",
|
|
407
|
+
"filePath":"src/gitnexus/coverage.ts","startLine":507,"endLine":864}],
|
|
408
|
+
"ftsAvailable":false,"total":1,...}}
|
|
409
|
+
```
|
|
410
|
+
|
|
313
411
|
## Scope: the project you are in, not a global list
|
|
314
412
|
|
|
315
413
|
The panel reports **the project the session's workspace points at**. It does not
|
|
@@ -330,13 +428,15 @@ Two situations the read-only half cannot resolve on its own:
|
|
|
330
428
|
- **初始化索引 / 增量刷新** — the index is missing or behind HEAD. This one the plugin
|
|
331
429
|
runs for you.
|
|
332
430
|
- **强制全量重构** — the incremental refresh has hung. GitNexus's update path is not
|
|
333
|
-
reliably terminating, and when it wedges a full rebuild is the only way out.
|
|
334
|
-
|
|
431
|
+
reliably terminating, and when it wedges a full rebuild is the only way out. This
|
|
432
|
+
one also has a button, behind its own destructive confirmation: the route implements
|
|
433
|
+
`--force`, and the dialog says what it rebuilds, how long it can take, and that the
|
|
434
|
+
index may be briefly unavailable.
|
|
335
435
|
|
|
336
|
-
|
|
337
|
-
every command as text, justified by "a plugin that spawns processes
|
|
338
|
-
permission system". That reasoning was wrong, and the correction is worth
|
|
339
|
-
precisely:
|
|
436
|
+
**Both maintenance actions run through the host's shell executor.** An earlier revision
|
|
437
|
+
handed over every command as text, justified by "a plugin that spawns processes
|
|
438
|
+
bypasses the permission system". That reasoning was wrong, and the correction is worth
|
|
439
|
+
stating precisely:
|
|
340
440
|
|
|
341
441
|
DSH's approval service governs **sandbox escalation** — widening the scope a session was
|
|
342
442
|
granted. Its audit pair must be turn-enclosed, which is why `ApprovalService.request()`
|
|
@@ -360,35 +460,50 @@ What the plugin commits to, and what is tested:
|
|
|
360
460
|
the agent skill files in your tree — a far larger change than "refresh the index".
|
|
361
461
|
- **A confirmation before it starts**, stating the exact command, what it touches and
|
|
362
462
|
how long it takes.
|
|
463
|
+
- **The full rebuild is a separate confirmation.** It runs only when the request carries
|
|
464
|
+
`force=1`, its confirmation says it rebuilds the graph and FTS and may take minutes,
|
|
465
|
+
and its button is labelled 全量重建 rather than borrowing the incremental one.
|
|
363
466
|
- **Cancellable**, with a ten-minute ceiling by default (`analyzeTimeoutMs`).
|
|
364
467
|
|
|
365
|
-
The full rebuild
|
|
366
|
-
`--force`.
|
|
367
|
-
|
|
468
|
+
The full rebuild used to have no button because the host route did not implement
|
|
469
|
+
`--force`. The route does now, and the button runs exactly the command its dialog
|
|
470
|
+
shows — a button that quietly ran something other than its label would still be worse
|
|
471
|
+
than no button.
|
|
368
472
|
|
|
369
|
-
The commands
|
|
370
|
-
in every deployment:
|
|
473
|
+
The commands shown and executed are not a bare `gitnexus analyze`, because that does not
|
|
474
|
+
work in every deployment:
|
|
371
475
|
|
|
372
476
|
```
|
|
373
477
|
$env:GITNEXUS_MEMORY='off'; $env:NODE_OPTIONS='--max-old-space-size=8192'; \
|
|
478
|
+
$env:GITNEXUS_HOME='<project>\.gitnexus\plugin-home'; \
|
|
374
479
|
gitnexus analyze --index-only '<project>'
|
|
375
480
|
|
|
376
481
|
$env:GITNEXUS_MEMORY='off'; $env:NODE_OPTIONS='--max-old-space-size=8192'; \
|
|
482
|
+
$env:GITNEXUS_HOME='<project>\.gitnexus\plugin-home'; \
|
|
377
483
|
gitnexus analyze --index-only --force '<project>'
|
|
378
484
|
```
|
|
379
485
|
|
|
380
486
|
- `GITNEXUS_MEMORY=off` — the CLI otherwise re-spawns itself with a larger heap over
|
|
381
487
|
piped stdio, which a confined sandbox denies (`spawn EPERM`).
|
|
382
488
|
- `NODE_OPTIONS=--max-old-space-size=8192` — supplies the heap that respawn wanted.
|
|
489
|
+
- `GITNEXUS_HOME=<project>\.gitnexus\plugin-home` — the global registry write would
|
|
490
|
+
otherwise go to `~/.gitnexus`, outside a confined host's writable scope. A failed
|
|
491
|
+
registry write leaves the index marked `incremental-in-progress` and incomplete.
|
|
492
|
+
The plugin defaults this redirect to the project's own `.gitnexus/plugin-home`;
|
|
493
|
+
`gitnexusHome` overrides it.
|
|
383
494
|
- `--index-only` — the default `analyze` also rewrites `AGENTS.md`, `CLAUDE.md` and
|
|
384
495
|
agent skill files inside your repository. A maintenance action must not edit the
|
|
385
496
|
working tree.
|
|
386
497
|
|
|
387
|
-
`--skip-fts` is **
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
498
|
+
`--skip-fts` is **adaptive**, not a static default. An index whose manifest says
|
|
499
|
+
`capabilities.fts.status: available` gets no flag; an index without FTS gets
|
|
500
|
+
`--skip-fts`, because the extension's install is an out-of-process step a confined
|
|
501
|
+
host denies (`spawn EPERM`), and that failure aborts the refresh. This matters in both
|
|
502
|
+
directions: measured on a 39-file repository, putting `--skip-fts` on an index that
|
|
503
|
+
already has FTS forces a full graph-store rebuild — 179.22 s against 8.57 s, a 21×
|
|
504
|
+
penalty — while omitting it on an index without FTS makes the refresh fail outright.
|
|
505
|
+
Setting `skipFts: true` forces the flag; there is no config that forces FTS on, because
|
|
506
|
+
enabling it is a repair (`gitnexus analyze --repair-fts`), not an incremental refresh.
|
|
392
507
|
|
|
393
508
|
The panel prints these rationales next to the commands, so they do not look
|
|
394
509
|
arbitrary. `src/gitnexus/commands.js` is pure and asserted verbatim by tests.
|
|
@@ -408,24 +523,27 @@ because this package declares `dsh.bundle`.
|
|
|
408
523
|
|
|
409
524
|
## Known limits
|
|
410
525
|
|
|
411
|
-
- **
|
|
412
|
-
dependencies and never imports `gitnexus`; it reads an index another tool
|
|
413
|
-
and, when it can, deep-imports the upstream scan primitives at runtime. That
|
|
414
|
-
keeps it a pure observer, but it makes "the operator has no GitNexus" a
|
|
415
|
-
state
|
|
416
|
-
`library-only` / `absent
|
|
417
|
-
PATH"
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
526
|
+
- **Detection is a filesystem probe, not an execution check.** The plugin declares no
|
|
527
|
+
runtime dependencies and never imports `gitnexus`; it reads an index another tool
|
|
528
|
+
produced and, when it can, deep-imports the upstream scan primitives at runtime. That
|
|
529
|
+
design keeps it a pure observer, but it makes "the operator has no GitNexus" a
|
|
530
|
+
reachable state — so `src/gitnexus/toolchain.ts` probes it in three states (`ready` /
|
|
531
|
+
`library-only` / `absent`), separating "the library tree exists" from "a CLI is on
|
|
532
|
+
PATH" because they gate different promises. The refresh runner consults it **before
|
|
533
|
+
spawning anything**: with no CLI it reports `unavailable` and tells the operator to
|
|
534
|
+
install one, rather than starting a process that cannot work. Spawning the CLI to ask
|
|
535
|
+
its version would be the direct test, but a confined process denies piped stdio, so
|
|
536
|
+
the probe only stats the filesystem. The engine degrades on its own too — `scan.ts`
|
|
537
|
+
falls back to its own walker and reports `primitives: 'fallback'`, and the built-in
|
|
538
|
+
size caps apply.
|
|
422
539
|
- **A report that reused GitNexus's scan rules and one that fell back to an
|
|
423
|
-
approximation are still not distinguished
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
therefore carry
|
|
540
|
+
approximation are still not distinguished per file.** The toolchain verdict travels
|
|
541
|
+
with the report, the language breakdown carries `detector: "gitnexus" | "builtin"`,
|
|
542
|
+
and the fallback rows are never labelled *parsed* — but the remaining per-file numbers
|
|
543
|
+
do not carry a provenance marker, so a fallback walk is not labelled as one where
|
|
544
|
+
those numbers are shown. The built-in walker deliberately does **not** implement
|
|
545
|
+
upstream's ignore rules faithfully, and its uncovered-file count can therefore carry
|
|
546
|
+
false positives.
|
|
429
547
|
- **Installing GitNexus from the panel has never been run against a real network.** The
|
|
430
548
|
command shape is verified (`npm install --prefix … --no-audit --no-fund`, no hardcoded
|
|
431
549
|
registry), the runner's state machine is covered by fourteen assertions, and the
|
|
@@ -433,7 +551,9 @@ because this package declares `dsh.bundle`.
|
|
|
433
551
|
What is **not** verified is the download and compile itself: it is several hundred
|
|
434
552
|
megabytes and was never executed from inside a confined DSH process. Treat the first
|
|
435
553
|
authorised install on any machine as untested, and fall back to the manual command if
|
|
436
|
-
it fails — which is why that command is offered first.
|
|
554
|
+
it fails — which is why that command is offered first. What *is* verified by tests is
|
|
555
|
+
that the installed prefix is the one the reader, the language detector and the analyze
|
|
556
|
+
runner all resolve; the download and compile remain unverified.
|
|
437
557
|
- **`--omit=optional` saves about 486 MB of that install, and is not used by default.**
|
|
438
558
|
Measured: a full GitNexus tree is 998.9 MB, and omitting the optional dependencies
|
|
439
559
|
gives 513.2 MB by dropping `onnxruntime-node` (287 MB), `onnxruntime-web` (139 MB) and
|
|
@@ -475,10 +595,38 @@ because this package declares `dsh.bundle`.
|
|
|
475
595
|
git-tracked files; real data killed it — 8 of the "missing" tracked files in a
|
|
476
596
|
37-file repo were dotfiles excluded by the walker's `dot: false`, and 2 indexed
|
|
477
597
|
files were untracked. The walker's own rules are the only honest denominator.
|
|
478
|
-
- **
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
598
|
+
- **Keyword search is graph name/path first, with a source-text fallback.** The graph
|
|
599
|
+
mode finds symbols and files whose *names* or *paths* contain the query; it does not
|
|
600
|
+
search function bodies, comments or descriptions. The fallback (`mode: "text"`) does
|
|
601
|
+
search line text, but only in the files the index manifest lists, and only when the
|
|
602
|
+
graph helper cannot start. Content-level search as a first-class mode is GitNexus's
|
|
603
|
+
FTS surface, and on this machine the FTS extension fails to load
|
|
604
|
+
(`libfts.lbug_extension` missing) and the current index was built with `--skip-fts`.
|
|
605
|
+
The panel labels the two modes separately (符号名 / 文件路径 vs 源码关键词(回退)) and
|
|
606
|
+
never presents a text hit as a graph hit.
|
|
607
|
+
- **Search needs a child Node process for the graph path.** The host's Electron Node
|
|
608
|
+
cannot load the LadybugDB addon (ABI mismatch), so the query is delegated to
|
|
609
|
+
`lib/bin/search-helper.js` under the system Node 24. This is deliberate, not a
|
|
610
|
+
workaround to remove: an in-process search fails on the host with the DLL
|
|
611
|
+
initialization error above. If the shell executor is unavailable (measured on this
|
|
612
|
+
machine: the Windows `windows-acl-run` sandbox cannot create its temp directory),
|
|
613
|
+
search does **not** fail — it falls back to the bounded source-text scan and labels
|
|
614
|
+
the result `text`. The graph query remains the preferred path when the helper can
|
|
615
|
+
start.
|
|
616
|
+
- **The source fallback is not the graph.** It searches line text in the files the
|
|
617
|
+
index manifest lists, not symbol relationships; code paths are searched before
|
|
618
|
+
documentation, and the file/byte/match caps can truncate a large repository. The
|
|
619
|
+
panel's card title changes to 源码关键词(回退) and the warning names the fallback,
|
|
620
|
+
so a text hit is never presented as a graph hit.
|
|
621
|
+
- **Panel effects and re-render are still not automated.** `react-dom` is not installed
|
|
622
|
+
on this machine, so rendering uses a single-pass shim: `useState` yields its initial
|
|
623
|
+
value and `useEffect` never runs. The pure view is covered; the fetch lifecycle is
|
|
624
|
+
not. The panel has now been checked once against the real right sidebar, and that
|
|
625
|
+
check is what exposed the two-column layout clipping the language card at a narrow
|
|
626
|
+
pane edge, the grey single-bucket chart, the invented `--dsw-color-*` tokens, the
|
|
627
|
+
raw English `index` cap source, and the `--skip-fts` config default. Those are
|
|
628
|
+
fixed, but a future prop or layout change can still pass every test here without
|
|
629
|
+
being seen in a browser.
|
|
630
|
+
- **Install → initialize has not been exercised end to end against a real npm install.**
|
|
631
|
+
The managed-prefix wiring, the auto-chain gate, and the analyze command are covered by
|
|
632
|
+
tests; the several-hundred-megabyte download and native compile are not.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Search helper, run by the **system Node** rather than the DSH host.
|
|
4
|
+
*
|
|
5
|
+
* The host is Electron's Node and cannot load GitNexus's LadybugDB native addon
|
|
6
|
+
* (ABI mismatch: "A dynamic link library (DLL) initialization routine failed").
|
|
7
|
+
* This process is started with the platform Node that the CLI already uses, imports
|
|
8
|
+
* the same adapter, runs one read-only query, and prints exactly one JSON object for
|
|
9
|
+
* the host to parse.
|
|
10
|
+
*
|
|
11
|
+
* Invocation:
|
|
12
|
+
* node search-helper.js <repo> <sanitized-query> [limit] [managedPrefix]
|
|
13
|
+
*
|
|
14
|
+
* Success: `{ "ok": true, "report": SearchReport }`
|
|
15
|
+
* Failure: `{ "ok": false, "status": <number>, "code": <SearchErrorCode>, "message": string }`
|
|
16
|
+
*
|
|
17
|
+
* It always exits 0 for a reported failure, so the host reads a structured answer
|
|
18
|
+
* instead of inferring one from an exit code. A process-level crash (native fault)
|
|
19
|
+
* is the one case the host handles from an unparseable stdout/stderr pair.
|
|
20
|
+
*/
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=search-helper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-helper.d.ts","sourceRoot":"","sources":["../../src/bin/search-helper.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;GAkBG"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Search helper, run by the **system Node** rather than the DSH host.
|
|
4
|
+
*
|
|
5
|
+
* The host is Electron's Node and cannot load GitNexus's LadybugDB native addon
|
|
6
|
+
* (ABI mismatch: "A dynamic link library (DLL) initialization routine failed").
|
|
7
|
+
* This process is started with the platform Node that the CLI already uses, imports
|
|
8
|
+
* the same adapter, runs one read-only query, and prints exactly one JSON object for
|
|
9
|
+
* the host to parse.
|
|
10
|
+
*
|
|
11
|
+
* Invocation:
|
|
12
|
+
* node search-helper.js <repo> <sanitized-query> [limit] [managedPrefix]
|
|
13
|
+
*
|
|
14
|
+
* Success: `{ "ok": true, "report": SearchReport }`
|
|
15
|
+
* Failure: `{ "ok": false, "status": <number>, "code": <SearchErrorCode>, "message": string }`
|
|
16
|
+
*
|
|
17
|
+
* It always exits 0 for a reported failure, so the host reads a structured answer
|
|
18
|
+
* instead of inferring one from an exit code. A process-level crash (native fault)
|
|
19
|
+
* is the one case the host handles from an unparseable stdout/stderr pair.
|
|
20
|
+
*/
|
|
21
|
+
import { SearchError, searchSymbols } from '../gitnexus/search.js';
|
|
22
|
+
/** Write the one object, then exit once stdout has flushed. */
|
|
23
|
+
function emit(payload) {
|
|
24
|
+
const text = JSON.stringify(payload);
|
|
25
|
+
process.stdout.write(text, () => process.exit(0));
|
|
26
|
+
// A native handle can keep the event loop alive; the payload is already queued.
|
|
27
|
+
setTimeout(() => process.exit(0), 2000).unref();
|
|
28
|
+
}
|
|
29
|
+
const [, , repoArg, queryArg, limitArg, managedArg] = process.argv;
|
|
30
|
+
if (typeof repoArg !== 'string' || repoArg === '' || typeof queryArg !== 'string') {
|
|
31
|
+
emit({
|
|
32
|
+
ok: false,
|
|
33
|
+
status: 400,
|
|
34
|
+
code: 'invalid-query',
|
|
35
|
+
message: 'usage: search-helper <repo> <query> [limit] [managedPrefix]',
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
const parsedLimit = limitArg === undefined ? undefined : Number.parseInt(limitArg, 10);
|
|
40
|
+
const limit = parsedLimit === undefined || !Number.isFinite(parsedLimit) ? undefined : parsedLimit;
|
|
41
|
+
try {
|
|
42
|
+
const report = await searchSymbols(repoArg, queryArg, {
|
|
43
|
+
limit,
|
|
44
|
+
managedPrefix: managedArg === undefined || managedArg === '' ? undefined : managedArg,
|
|
45
|
+
});
|
|
46
|
+
emit({ ok: true, report });
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
emit({
|
|
50
|
+
ok: false,
|
|
51
|
+
status: error instanceof SearchError ? error.status : 500,
|
|
52
|
+
code: error instanceof SearchError ? error.code : 'search-failed',
|
|
53
|
+
message: error instanceof Error ? error.message : String(error),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=search-helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-helper.js","sourceRoot":"","sources":["../../src/bin/search-helper.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEnE,+DAA+D;AAC/D,SAAS,IAAI,CAAC,OAAgB;IAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,gFAAgF;IAChF,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;AAClD,CAAC;AAED,MAAM,CAAC,EAAE,AAAD,EAAG,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;AAEnE,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,EAAE,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;IAClF,IAAI,CAAC;QACH,EAAE,EAAE,KAAK;QACT,MAAM,EAAE,GAAG;QACX,IAAI,EAAE,eAAe;QACrB,OAAO,EAAE,6DAA6D;KACvE,CAAC,CAAC;AACL,CAAC;KAAM,CAAC;IACN,MAAM,WAAW,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACvF,MAAM,KAAK,GAAG,WAAW,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC;IACnG,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,OAAO,EAAE,QAAQ,EAAE;YACpD,KAAK;YACL,aAAa,EAAE,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU;SACtF,CAAC,CAAC;QACH,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC;YACH,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,KAAK,YAAY,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG;YACzD,IAAI,EAAE,KAAK,YAAY,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe;YACjE,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAChE,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|