@karmaniverous/jeeves-watcher-openclaw 0.16.1 → 0.17.0
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/LICENSE +28 -0
- package/README.md +7 -5
- package/dist/index.js +1584 -223
- package/dist/skills/jeeves-watcher/SKILL.md +156 -114
- package/dist/src/apiTool.d.ts +11 -3
- package/dist/src/auth.test.d.ts +5 -0
- package/dist/src/configTools.d.ts +14 -0
- package/dist/src/configTools.test.d.ts +5 -0
- package/dist/src/constants.d.ts +1 -1
- package/dist/src/helpers.d.ts +15 -3
- package/dist/src/http.d.ts +19 -0
- package/dist/src/http.test.d.ts +5 -0
- package/dist/src/toolGating.d.ts +11 -7
- package/dist/src/watcherComponent.d.ts +4 -2
- package/dist/src/watcherTools.d.ts +7 -1
- package/openclaw.plugin.json +10 -1
- package/package.json +12 -10
|
@@ -12,9 +12,13 @@ The watcher is an HTTP API running as a background service (typically NSSM on Wi
|
|
|
12
12
|
|
|
13
13
|
**Default port:** 1936 (configurable via `api.port` in watcher config) **Non-default port:** If the watcher runs on a different port, the user must set `plugins.entries.jeeves-watcher-openclaw.config.apiUrl` in `openclaw.json`. The plugin cannot auto-discover a non-default port.
|
|
14
14
|
|
|
15
|
-
**
|
|
15
|
+
**API key:** If the watcher sets `api.apiKey`, every route except `GET /status` needs `Authorization: Bearer <key>`. The tools send it from `plugins.entries.jeeves-watcher-openclaw.config.apiKey` (or the `JEEVES_WATCHER_API_KEY` env var). A missing or wrong key comes back as `HTTP 401 unauthorized: the watcher API requires an API key. Provide it via plugins.entries.jeeves-watcher-openclaw.config.apiKey or the JEEVES_WATCHER_API_KEY env var.` (or, when a key was sent, `... rejected the API key. Check ... against the service's api.apiKey.`). When calling the API directly, add the header yourself. Never echo the key.
|
|
16
16
|
|
|
17
|
-
**
|
|
17
|
+
**Tool errors:** Tool error text is prefixed `Error: `. Any other non-2xx response reads `HTTP <status> <code>: <message>`, where `<code>` is the server's machine-readable error code (e.g. `HTTP 400 invalid_request: Validation failed`, `HTTP 503 scan_in_progress: Scan in progress: ...`). Branch on the code, not the message. Structured `details` (Zod issues, per-property validation failures) are in the HTTP response body only; call the API directly when you need them. An unreachable service reads `Service not reachable at <url>.` with a hint to set `apiUrl`. (`watcher_status` and `watcher_service` come from the shared Jeeves core toolset and word their own errors.)
|
|
18
|
+
|
|
19
|
+
**Health check:** `GET /status` returns `name`, `version`, `uptime`, `status` (`healthy`/`degraded`/`unhealthy`), and a `health` object containing `collection` (`name`, `pointCount`, `dimensions`), `reindex` progress, and `initialScan` progress.
|
|
20
|
+
|
|
21
|
+
**Mental model:** The `watcher_*` tools are thin HTTP wrappers. Each tool call translates to an HTTP request to the watcher API. When tools are available, use them. When they're not (e.g., different session, plugin not loaded), you can hit the API directly. Replace `<PORT>` below with the configured port (default 1936; check `plugins.entries.jeeves-watcher-openclaw.config.apiUrl` in `openclaw.json` if overridden), and add `-H "Authorization: Bearer <key>"` when the service sets `api.apiKey`:
|
|
18
22
|
|
|
19
23
|
```
|
|
20
24
|
# Health check
|
|
@@ -35,24 +39,27 @@ curl http://127.0.0.1:<PORT>/config
|
|
|
35
39
|
| --- | --- | --- |
|
|
36
40
|
| `/status` | GET | Health check, uptime, collection stats |
|
|
37
41
|
| `/search` | POST | Semantic search (main query interface) |
|
|
38
|
-
| `/config` | GET |
|
|
42
|
+
| `/config` | GET | Public resolved config (allow-listed keys plus `issues`); optional `?path=<jsonpath>` filter |
|
|
39
43
|
| `/config/validate` | POST | Validate candidate config |
|
|
40
44
|
| `/config/apply` | POST | Apply config changes |
|
|
41
45
|
| `/reindex` | POST | Trigger reindex |
|
|
42
|
-
| `/metadata` | POST | Enrich document metadata |
|
|
46
|
+
| `/metadata` | POST | Enrich document metadata (file path or source reference) |
|
|
43
47
|
| `/scan` | POST | Filter-only point query (no embeddings) |
|
|
44
|
-
| `/walk` | POST |
|
|
45
|
-
| `/issues` | GET | Runtime
|
|
48
|
+
| `/walk` | POST | Watched-file listing with glob intersection |
|
|
49
|
+
| `/issues` | GET | Runtime processing failures (file paths and source references) |
|
|
50
|
+
| `/documents` | POST | Notify changed source documents (`{ source, rule }`) |
|
|
51
|
+
| `/documents/delete` | POST | Delete source documents by reference or filter |
|
|
46
52
|
| `/rules/register` | POST | Register virtual inference rules (auto-triggers rules reindex) |
|
|
47
|
-
| `/rules/unregister` | DELETE | Remove virtual rules by source |
|
|
53
|
+
| `/rules/unregister` | DELETE | Remove virtual rules by source (`{ source }` body) |
|
|
48
54
|
| `/rules/unregister/:source` | DELETE | Remove virtual rules by source (parameterized) |
|
|
49
|
-
| `/rules/reapply` | POST | Re-apply rules to
|
|
55
|
+
| `/rules/reapply` | POST | Re-apply rules to indexed files matching `globs` |
|
|
50
56
|
| `/points/delete` | POST | Delete points matching a Qdrant filter |
|
|
51
|
-
| `/render` | POST | Render a
|
|
57
|
+
| `/render` | POST | Render a document (file path or source reference) through its rule |
|
|
52
58
|
| `/search/facets` | GET | Get search facet values |
|
|
53
|
-
| `/rebuild-metadata` | POST | Rebuild enrichment
|
|
59
|
+
| `/rebuild-metadata` | POST | Rebuild the enrichment store from Qdrant file point payloads |
|
|
54
60
|
| `/config/schema` | GET | Get config JSON schema |
|
|
55
|
-
| `/config/match` | POST |
|
|
61
|
+
| `/config/match` | POST | Test file paths against inference rules and watch scope |
|
|
62
|
+
| `/vcs/*` | GET/POST | Version tracking (`status`, `history`, `show`, `diff`, `check-exclusion`, `revert`, `exclude`) |
|
|
56
63
|
|
|
57
64
|
**If the watcher is unreachable:** Check the service status (`nssm status jeeves-watcher` on Windows), check the configured port in the watcher config file, and check logs for startup errors.
|
|
58
65
|
|
|
@@ -84,7 +91,7 @@ You have access to a **semantic archive** of your human's working world. Documen
|
|
|
84
91
|
|
|
85
92
|
- **Renaming, moving, or reorganizing watched directories.** The watcher has **move detection** enabled by default (`watch.moveDetection.enabled: true`). When a file is moved, chokidar emits unlink + add events; the `MoveCorrelator` buffers the unlink, matches it with the add via content hash, and processes it as a zero-embedding move (point ID remap, metadata re-inference, enrichment migration). **No re-embedding cost for moves.** However, if a rename is blocked (e.g., by a file lock from the watcher or another service), **do NOT work around it by creating new directories and copying/moving files**. That creates duplicate embeddings at the new paths while the old paths still exist. Instead: stop the blocking service, perform the rename, restart.
|
|
86
93
|
- **Changing `watch.paths` to add large directory trees.** Adding a new watch root triggers initial indexing of every matching file under it.
|
|
87
|
-
- **Running `scope: "full"` reindex.**
|
|
94
|
+
- **Running `scope: "full"` reindex.** Every watched file is re-extracted (a file whose text to embed changed, or that was never indexed, is re-embedded) and every indexed source document is retrieved through its callback and always re-embedded. Use `scope: "rules"` for inference rule changes (no file re-embedding; only metadata reapplication).
|
|
88
95
|
- **Any bulk file operation** (mass copy, mass move, template-based file generation) under watched paths.
|
|
89
96
|
|
|
90
97
|
**The right instinct when blocked:** If a filesystem operation fails because a service has a lock, the correct response is to stop the service, do the operation, and restart — NOT to find a creative workaround. Creative workarounds in the presence of a live watcher are how you accidentally trigger re-embedding of tens of thousands of files.
|
|
@@ -102,7 +109,7 @@ The plugin is a standard OpenClaw plugin. On a Jeeves box, `jeeves install watch
|
|
|
102
109
|
If the watcher service is already running and healthy:
|
|
103
110
|
|
|
104
111
|
1. **Search** — use `watcher_search` with a natural language query and optional metadata filters
|
|
105
|
-
2. **Read source** — use `read` (standard file read) with `file_path` from search results for full document content
|
|
112
|
+
2. **Read source** — use `read` (standard file read) with `file_path` from search results for full document content. Source documents (points carrying `source`, such as `app://chat/thread/42`, and no `file_path`) are not files: their content comes from the source's callback (`POST /render` with `{ "source": "<ref>" }`).
|
|
106
113
|
|
|
107
114
|
## Bootstrap (First-Time Setup)
|
|
108
115
|
|
|
@@ -281,10 +288,10 @@ Then generate a starter config file. Example minimal config:
|
|
|
281
288
|
}
|
|
282
289
|
```
|
|
283
290
|
|
|
284
|
-
Write the config to a sensible location (e.g., `~/.config/jeeves-watcher.config.json` on Linux, or alongside the user's workspace). Validate with:
|
|
291
|
+
Write the config to a sensible location (e.g., `~/.config/jeeves-watcher.config.json` on Linux, or alongside the user's workspace). Validate it against the config schema (offline; no running service needed) with:
|
|
285
292
|
|
|
286
293
|
```bash
|
|
287
|
-
jeeves-watcher validate -c <config-path>
|
|
294
|
+
jeeves-watcher config validate -c <config-path>
|
|
288
295
|
```
|
|
289
296
|
|
|
290
297
|
### Step 6: Register and Start as a Service
|
|
@@ -316,9 +323,9 @@ sudo systemctl enable --now jeeves-watcher
|
|
|
316
323
|
**Windows (NSSM):**
|
|
317
324
|
|
|
318
325
|
```powershell
|
|
319
|
-
jeeves-watcher service install
|
|
326
|
+
jeeves-watcher service install -c <config-path>
|
|
320
327
|
# Or manually:
|
|
321
|
-
nssm install jeeves-watcher
|
|
328
|
+
nssm install jeeves-watcher (Get-Command jeeves-watcher).Source start -c <config-path>
|
|
322
329
|
nssm set jeeves-watcher AppEnvironmentExtra GOOGLE_API_KEY=<key>
|
|
323
330
|
nssm start jeeves-watcher
|
|
324
331
|
```
|
|
@@ -337,7 +344,7 @@ Call `watcher_status` (or `curl http://127.0.0.1:1936/status`). Confirm:
|
|
|
337
344
|
- Qdrant collection exists with expected dimensions (3072)
|
|
338
345
|
- Point count is increasing (initial indexing in progress)
|
|
339
346
|
|
|
340
|
-
If the point count is 0 after a minute, check `watcher_issues` for
|
|
347
|
+
If the point count is 0 after a minute, check `watcher_issues` for processing failures.
|
|
341
348
|
|
|
342
349
|
### Step 8: Orientation
|
|
343
350
|
|
|
@@ -359,25 +366,31 @@ On sessions after bootstrap is complete:
|
|
|
359
366
|
|
|
360
367
|
## Tools
|
|
361
368
|
|
|
369
|
+
The plugin registers 18 tools: `watcher_status`, `watcher_config`, `watcher_config_apply`, `watcher_service`, `watcher_search`, `watcher_enrich`, `watcher_validate`, `watcher_reindex`, `watcher_scan`, `watcher_issues`, `watcher_walk`, and the seven `watcher_vcs_*` tools (see [Version Tracking](#version-tracking)).
|
|
370
|
+
|
|
362
371
|
### `watcher_search`
|
|
363
372
|
|
|
364
|
-
Semantic search over indexed documents.
|
|
373
|
+
Semantic search over indexed documents (`POST /search`).
|
|
365
374
|
|
|
366
|
-
- `query` (string, required) — natural language search query
|
|
367
|
-
- `limit` (number, optional) — max results, default 10
|
|
368
|
-
- `offset` (number, optional) — skip N results for pagination
|
|
375
|
+
- `query` (string, required) — natural language search query (non-empty)
|
|
376
|
+
- `limit` (number, optional) — max results (positive integer), default 10
|
|
377
|
+
- `offset` (number, optional) — skip N results for pagination (non-negative integer)
|
|
369
378
|
- `filter` (object, optional) — Qdrant filter for metadata filtering
|
|
370
379
|
|
|
380
|
+
Returns an array of `{ id, score, payload }` ordered by score (see [Search Result Shape](#search-result-shape)). A filter Qdrant rejects is `400 invalid_request`; an exhausted embedding budget is `503 embedding_unavailable`.
|
|
381
|
+
|
|
371
382
|
### `watcher_enrich`
|
|
372
383
|
|
|
373
|
-
Set or update metadata on a document.
|
|
384
|
+
Set or update metadata on a document (`POST /metadata`).
|
|
374
385
|
|
|
375
|
-
- `path` (string, required) — file path of the document
|
|
386
|
+
- `path` (string, required) — file path of the document (absolute or watched path)
|
|
376
387
|
- `metadata` (object, required) — key-value metadata to merge
|
|
377
388
|
|
|
389
|
+
Returns `{ ok: true, matched_rules }`. The tool addresses files only; to enrich a source document, call `POST /metadata` directly with `{ "source": "<name>://<id>", "metadata": { ... } }` (exactly one of `path` or `source`).
|
|
390
|
+
|
|
378
391
|
### `watcher_status`
|
|
379
392
|
|
|
380
|
-
Service health check. Returns `name`, `version`, `uptime`, `status`, and `health` object
|
|
393
|
+
Service health check (`GET /status`, never needs the API key). Returns `name`, `version`, `uptime`, `status`, and a `health` object: `collection` (`name`, `pointCount`, `dimensions`), `reindex` (`active`; while active also `scope`, `startedAt`, `filesProcessed`, `totalFiles`), and `initialScan`.
|
|
381
394
|
|
|
382
395
|
After a service restart, the `health.initialScan` field shows scan progress:
|
|
383
396
|
|
|
@@ -388,41 +401,47 @@ Use this to determine if the service is still initializing after a restart.
|
|
|
388
401
|
|
|
389
402
|
### `watcher_config`
|
|
390
403
|
|
|
391
|
-
Query the effective runtime config via JSONPath. Returns the full resolved merged document when no path is provided.
|
|
404
|
+
Query the effective runtime config via JSONPath (`GET /config`). Returns the full resolved merged document when no path is provided.
|
|
392
405
|
|
|
393
406
|
- `path` (string, optional) — JSONPath expression
|
|
394
407
|
|
|
408
|
+
The document holds only the allow-listed keys `description`, `watch`, `configWatch`, `search`, `schemas`, `inferenceRules`, `mapHelpers`, `templateHelpers`, `maps`, `templates`, plus `issues` (the current issues). `api`, `sources`, `embedding`, `vectorStore` (and their keys) are never included. Each rule carries `source` (`config`, or the registering source of a virtual rule) and `values` (the runtime values index). File references (`map`, `maps`, `templates`) and named schema references are always resolved. An invalid JSONPath is `400 invalid_request`.
|
|
409
|
+
|
|
395
410
|
### `watcher_validate`
|
|
396
411
|
|
|
397
|
-
Validate config and optionally test file paths.
|
|
412
|
+
Validate config and optionally test file paths (`POST /config/validate`).
|
|
398
413
|
|
|
399
414
|
- `config` (object, optional) — candidate config (partial or full). Omit to validate current config.
|
|
400
415
|
- `testPaths` (string[], optional) — file paths to test against the config
|
|
401
416
|
|
|
402
|
-
Partial configs
|
|
417
|
+
Partial configs are merged into the running config shallowly: each top-level key replaces the running value, except `inferenceRules`, which merge by rule name. This differs from `watcher_config_apply` (deep merge), so pass a whole top-level object (e.g. all of `watch`) when validating a change inside it. Returns `{ valid: false, errors: [{ path, message }] }`, or `{ valid: true, warnings?, testResults? }`, where each test result is `{ path, matchedRules, metadata, error? }` (`error: "File not found"` when the path cannot be read). Validation problems come back in a `200` body, so this is the place to see them in full.
|
|
403
418
|
|
|
404
419
|
### `watcher_config_apply`
|
|
405
420
|
|
|
406
|
-
Apply config changes
|
|
421
|
+
Apply config changes (`POST /config/apply`, sent as `{ patch: config }`).
|
|
407
422
|
|
|
408
423
|
- `config` (object, required) — full or partial config to apply
|
|
409
424
|
|
|
410
|
-
Partial configs are deep-merged into the
|
|
425
|
+
Partial configs are deep-merged into the config file the service runs from (objects recursively, arrays replaced, `inferenceRules` by rule name), so `{}` or a single key is valid. The merged result is validated and written to disk, then the `configWatch.reindex` scope (default `issues`) runs; that reindex covers files only. With `configWatch.enabled` (default `true`) the service picks up the written file without a restart, including new/removed watch paths (the filesystem watcher is rebuilt), inference rule changes, move detection settings, and gitignore filter updates.
|
|
426
|
+
|
|
427
|
+
Returns `{ applied: true, config }`. `config` is redacted through the same allow-list as `GET /config`: `api`, `sources` and provider keys are never echoed. When the file was written but the post-write apply step failed, the body also carries `warning` (a string describing the failure). An invalid merged config is a tool error reading `HTTP 400 invalid_request: Config validation failed` (the Zod `issues` are only in the HTTP body), so run `watcher_validate` first. A config file the service cannot read or write is a generic `HTTP 500 internal_error`, with the cause in the service log.
|
|
411
428
|
|
|
412
429
|
### `watcher_reindex`
|
|
413
430
|
|
|
414
|
-
Trigger a reindex operation. Non-prune scopes return a `plan` object showing blast area
|
|
431
|
+
Trigger a reindex operation (`POST /reindex`). Non-prune scopes return a `plan` object showing the blast area; the live run reuses the same targets. A live prune (non-dry-run) returns immediately without a plan.
|
|
415
432
|
|
|
416
433
|
**Parameters:**
|
|
417
434
|
|
|
418
|
-
- `scope` (string, optional) — Reindex scope.
|
|
419
|
-
- `"rules"` — Re-apply inference rules to
|
|
420
|
-
- `"full"` — Re-extract
|
|
421
|
-
- `"issues"` — Re-process
|
|
422
|
-
- `"path"` — Re-
|
|
423
|
-
- `"prune"` — Delete Qdrant points for files no longer in watch scope (removed paths, gitignored files,
|
|
424
|
-
- `path` (string,
|
|
425
|
-
- `dryRun` (boolean, optional) — When `true`, compute and return the
|
|
435
|
+
- `scope` (string, optional) — Reindex scope. The tool sends `"rules"` when omitted (the HTTP API's own default is `"issues"`). One of:
|
|
436
|
+
- `"rules"` — Re-apply inference rules to every watched file (no re-embedding; changed values written, keys the rules no longer project removed). With `path`, only files matching those globs. Without `path`, every indexed source document is also retrieved through its callback and its stored rule re-applied: unchanged content gets a metadata-only update, and a document is re-embedded only if its rendered text changed.
|
|
437
|
+
- `"full"` — Re-extract and re-process every watched file (a file is re-embedded when the text to embed changed or it was never indexed), and retrieve and always re-embed every indexed source document. Clears the runtime values index first.
|
|
438
|
+
- `"issues"` — Re-process the documents in `watcher_issues`: failed files, and failed source references (with their stored rule, or the `rule` recorded on the issue when the document was never indexed).
|
|
439
|
+
- `"path"` — Re-process a specific file or all files under a directory. Requires `path`. Each target must be watched and not gitignored (`403 path_not_watched`) and must exist (`404 not_found`). Files only.
|
|
440
|
+
- `"prune"` — Delete Qdrant points for files no longer in watch scope (removed paths, gitignored files, deleted files). No re-embedding. Pure cleanup. Never selects source points (`source` set, no `file_path`).
|
|
441
|
+
- `path` (string | string[], optional) — Target file(s) or directories for `"path"` (required there), or globs narrowing `"rules"`. Ignored by other scopes.
|
|
442
|
+
- `dryRun` (boolean, optional) — When `true`, compute and return the plan without executing.
|
|
443
|
+
|
|
444
|
+
The tool has no `source` parameter. To re-process specific source references, call `POST /reindex` directly with `{ "scope": "path", "source": ["<name>://<id>", ...] }` (at most 1000): they are enqueued on the notify queue, are not tracked by `GET /status`, and send no completion callback. A reindex triggered by a config change (`watcher_config_apply`, config-file reload, rule registration) covers files only.
|
|
426
445
|
|
|
427
446
|
**Response (normal):**
|
|
428
447
|
|
|
@@ -434,7 +453,7 @@ Trigger a reindex operation. Non-prune scopes return a `plan` object showing bla
|
|
|
434
453
|
"total": 148000,
|
|
435
454
|
"toProcess": 148000,
|
|
436
455
|
"toDelete": 0,
|
|
437
|
-
"byRoot": { "
|
|
456
|
+
"byRoot": { "/data": 95000, "/srv/config": 3000 }
|
|
438
457
|
}
|
|
439
458
|
}
|
|
440
459
|
```
|
|
@@ -449,30 +468,33 @@ Trigger a reindex operation. Non-prune scopes return a `plan` object showing bla
|
|
|
449
468
|
"total": 562000,
|
|
450
469
|
"toProcess": 0,
|
|
451
470
|
"toDelete": 2300,
|
|
452
|
-
"byRoot": { "
|
|
471
|
+
"byRoot": { "/srv/app/node_modules": 1800, "/srv/app/.cache": 500 }
|
|
453
472
|
}
|
|
454
473
|
}
|
|
455
474
|
```
|
|
456
475
|
|
|
457
476
|
**Plan fields:**
|
|
458
477
|
|
|
459
|
-
- `total` —
|
|
460
|
-
- `toProcess` —
|
|
478
|
+
- `total` — Points scrolled (prune), or files plus source documents covered (other scopes).
|
|
479
|
+
- `toProcess` — Files plus source documents to process (0 for prune).
|
|
461
480
|
- `toDelete` — Points to delete (prune only, 0 for others).
|
|
462
|
-
- `byRoot` —
|
|
481
|
+
- `byRoot` — Files grouped by watch root (for prune: orphaned files), plus one entry per source name for source documents. Shows where the impact concentrates.
|
|
482
|
+
- `incomplete` — `true` when the prune scroll failed part-way and the plan is partial.
|
|
483
|
+
|
|
484
|
+
**Progress:** a live run (every scope except `path` with `source`) is tracked in `watcher_status` under `health.reindex` (`filesProcessed` / `totalFiles`, counting files plus source documents). A failing file or source document is logged and recorded; the rest of the run continues.
|
|
463
485
|
|
|
464
486
|
**Guidance:**
|
|
465
487
|
|
|
466
488
|
- Use `dryRun: true` before any large-blast operation to preview impact.
|
|
467
|
-
- `prune` is safe — it only deletes orphaned points, never re-embeds. Use after changing watch paths, fixing gitignore, or cleaning up stale data.
|
|
489
|
+
- `prune` is safe — it only deletes orphaned file points, never re-embeds. Use after changing watch paths, fixing gitignore, or cleaning up stale data.
|
|
468
490
|
- `prune` is NOT triggered by config-watch auto-reindex (too dangerous for auto-trigger).
|
|
469
491
|
|
|
470
492
|
### `watcher_scan`
|
|
471
493
|
|
|
472
|
-
Filter-only point query without vector search. Use for structural queries where the question has no semantic dimension.
|
|
494
|
+
Filter-only point query without vector search (`POST /scan`). Use for structural queries where the question has no semantic dimension.
|
|
473
495
|
|
|
474
496
|
- `filter` (object, required) — Qdrant filter object. Required to prevent accidental full-collection scans.
|
|
475
|
-
- `limit` (number, optional) — page size, default 100
|
|
497
|
+
- `limit` (number, optional) — page size (integer 1 to 1000), default 100
|
|
476
498
|
- `cursor` (string, optional) — opaque cursor from previous response for pagination
|
|
477
499
|
- `fields` (string[], optional) — payload fields to return (projection)
|
|
478
500
|
- `countOnly` (boolean, optional) — if true, return `{ count }` instead of points
|
|
@@ -481,7 +503,12 @@ Filter-only point query without vector search. Use for structural queries where
|
|
|
481
503
|
|
|
482
504
|
```json
|
|
483
505
|
{
|
|
484
|
-
"points": [
|
|
506
|
+
"points": [
|
|
507
|
+
{
|
|
508
|
+
"id": "uuid",
|
|
509
|
+
"payload": { "file_path": "/data/tickets/PROJ-123.json" }
|
|
510
|
+
}
|
|
511
|
+
],
|
|
485
512
|
"cursor": "opaque-string-or-null"
|
|
486
513
|
}
|
|
487
514
|
```
|
|
@@ -496,7 +523,7 @@ Filter-only point query without vector search. Use for structural queries where
|
|
|
496
523
|
|
|
497
524
|
- No `query` parameter — does NOT use embeddings
|
|
498
525
|
- No `score` field — results are unranked filter matches
|
|
499
|
-
- Cursor-based pagination (not offset-based)
|
|
526
|
+
- Cursor-based pagination (not offset-based); `cursor` is `null` on the last page
|
|
500
527
|
- Zero cost per call beyond Qdrant's filtered scroll
|
|
501
528
|
|
|
502
529
|
**Pagination pattern:**
|
|
@@ -512,29 +539,29 @@ do {
|
|
|
512
539
|
|
|
513
540
|
### `watcher_service`
|
|
514
541
|
|
|
515
|
-
Manage the watcher background service (install, uninstall, start, stop, restart, check status).
|
|
542
|
+
Manage the watcher background service (install, uninstall, start, stop, restart, check status). No HTTP call.
|
|
516
543
|
|
|
517
544
|
- `action` (string, required) — one of: `install`, `uninstall`, `start`, `stop`, `restart`, `status`
|
|
518
545
|
|
|
519
|
-
Returns the service manager's response. On Windows uses NSSM, on Linux
|
|
546
|
+
Returns the service manager's response. On Windows uses NSSM, on Linux systemd, on macOS launchd. Only `install` needs `configRoot` (see [Plugin Installation](#plugin-installation)).
|
|
520
547
|
|
|
521
548
|
### `watcher_issues`
|
|
522
549
|
|
|
523
|
-
Get runtime
|
|
550
|
+
Get runtime processing failures (`GET /issues`). Returns `{ count, issues: { [key]: IssueRecord[] } }`: `count` is the number of documents with issues, and each key is a file path or a source reference (`<name>://<id>`). Each `IssueRecord` has `type` (one of the [issue codes](#error-categories)), `message`, `timestamp`, and optionally `operation`, `property`, `rule`, `rules`, `types`, `details`.
|
|
524
551
|
|
|
525
552
|
### `watcher_walk`
|
|
526
553
|
|
|
527
|
-
|
|
554
|
+
List watched files matching globs (`POST /walk`). Returns matching file paths from the watcher's in-memory list of watched files across all configured watch roots.
|
|
528
555
|
|
|
529
|
-
- `globs` (string[], required) — glob patterns to intersect with watch paths
|
|
556
|
+
- `globs` (string[], required) — glob patterns to intersect with watch paths (non-empty; matched case-insensitively, dotfiles included)
|
|
530
557
|
|
|
531
558
|
**Response:**
|
|
532
559
|
|
|
533
560
|
```json
|
|
534
561
|
{
|
|
535
|
-
"paths": ["
|
|
562
|
+
"paths": ["/data/foo/.meta/meta.json", "/data/bar/.meta/meta.json"],
|
|
536
563
|
"matchedCount": 2,
|
|
537
|
-
"scannedRoots": ["
|
|
564
|
+
"scannedRoots": ["/data", "/srv/config"]
|
|
538
565
|
}
|
|
539
566
|
```
|
|
540
567
|
|
|
@@ -542,12 +569,12 @@ Walk watched filesystem paths with glob intersection. Returns matching file path
|
|
|
542
569
|
|
|
543
570
|
- Discover files matching a pattern across all watched directories (e.g., `["**/.meta/meta.json"]`)
|
|
544
571
|
- Enumerate files before rule registration to understand scope
|
|
545
|
-
- Find files that aren't yet indexed (no Qdrant dependency
|
|
572
|
+
- Find files that aren't yet indexed (no Qdrant dependency)
|
|
546
573
|
|
|
547
574
|
**Key differences from `watcher_scan`:**
|
|
548
575
|
|
|
549
|
-
-
|
|
550
|
-
- No embedding or indexing required
|
|
576
|
+
- Lists the files the filesystem watcher tracks, not the Qdrant index
|
|
577
|
+
- No embedding or indexing required, but the initial filesystem scan must be complete: until then the tool returns `HTTP 503 scan_in_progress` (check `health.initialScan` in `watcher_status`)
|
|
551
578
|
- Returns file paths only (no metadata, no vectors)
|
|
552
579
|
- Applies `watch.ignored` and gitignore filtering automatically
|
|
553
580
|
|
|
@@ -580,7 +607,7 @@ Walk watched filesystem paths with glob intersection. Returns matching file path
|
|
|
580
607
|
**Path prefix matching:**
|
|
581
608
|
|
|
582
609
|
```json
|
|
583
|
-
{ "must": [{ "key": "file_path", "match": { "text": "
|
|
610
|
+
{ "must": [{ "key": "file_path", "match": { "text": "/data/tickets" } }] }
|
|
584
611
|
```
|
|
585
612
|
|
|
586
613
|
**Count files in a domain (no point data transferred):**
|
|
@@ -660,15 +687,21 @@ Each result from `watcher_search` contains:
|
|
|
660
687
|
| Field | Type | Description |
|
|
661
688
|
| --- | --- | --- |
|
|
662
689
|
| `id` | string | Qdrant point ID |
|
|
663
|
-
| `score` | number | Similarity score
|
|
664
|
-
| `payload.file_path` | string |
|
|
690
|
+
| `score` | number | Similarity (or hybrid fused) score; higher = more relevant |
|
|
691
|
+
| `payload.file_path` | string | Normalized file path (file points only) |
|
|
692
|
+
| `payload.source` | string | Source reference `<name>://<id>` (source points only) |
|
|
693
|
+
| `payload.source_rule` | string | Designated rule of a source document (source points only) |
|
|
665
694
|
| `payload.chunk_text` | string | The matched text chunk |
|
|
666
|
-
| `payload.chunk_index` | number |
|
|
667
|
-
| `payload.total_chunks` | number | Total chunks for this
|
|
668
|
-
| `payload.
|
|
695
|
+
| `payload.chunk_index` | number | Zero-based chunk position within the document |
|
|
696
|
+
| `payload.total_chunks` | number | Total chunks for this document |
|
|
697
|
+
| `payload.line_start` | number | 1-indexed line where the chunk starts |
|
|
698
|
+
| `payload.line_end` | number | 1-indexed line where the chunk ends |
|
|
699
|
+
| `payload.created_at` | number | Creation timestamp (unix seconds) |
|
|
700
|
+
| `payload.modified_at` | number | Modification timestamp (unix seconds) |
|
|
701
|
+
| `payload.content_hash` | string | SHA-256 hash of the embedded text |
|
|
669
702
|
| `payload.matched_rules` | string[] | Names of inference rules that matched |
|
|
670
703
|
|
|
671
|
-
Additional metadata fields depend on the deployment's inference rules (e.g., `domain`, `status`, `author`). Use `watcher_config` to discover available fields.
|
|
704
|
+
`file_path` is not always present: a source point (a document indexed through a source callback) carries a non-empty `source` and no `file_path`. A file point may also carry a `source` written by its own rules; it is still a file point. Additional metadata fields depend on the deployment's inference rules (e.g., `domain`, `status`, `author`). Use `watcher_config` to discover available fields.
|
|
672
705
|
|
|
673
706
|
## Query Planning (Per Search Task)
|
|
674
707
|
|
|
@@ -678,10 +711,9 @@ Identify relevant rule(s) from the orientation model, then retrieve their schema
|
|
|
678
711
|
|
|
679
712
|
```
|
|
680
713
|
watcher_config: path="$.inferenceRules[?(@.name=='jira-issue')].schema"
|
|
681
|
-
resolve=["files","globals"]
|
|
682
714
|
```
|
|
683
715
|
|
|
684
|
-
Returns the
|
|
716
|
+
Returns the rule's schema array with named schema references and file references already resolved: properties, types, `set` expressions, `uiHint`, `enum`, etc.
|
|
685
717
|
|
|
686
718
|
**For select/multiselect fields without `enum` in schema:**
|
|
687
719
|
|
|
@@ -704,7 +736,7 @@ Use `uiHint` to determine filter construction strategy. **This table is explicit
|
|
|
704
736
|
| `text` | `{ "key": "<field>", "match": { "text": "<value>" } }` | Substring/keyword match |
|
|
705
737
|
| `select` | `{ "key": "<field>", "match": { "value": "<enum_value>" } }` | Exact match; use `enum` values from schema or runtime values index |
|
|
706
738
|
| `multiselect` | `{ "key": "<field>", "match": { "value": "<enum_value>" } }` | Any-element match on array field; use `enum` or runtime values index |
|
|
707
|
-
| `date` | `{ "key": "<field>", "range": { "gte": <unix_ts>, "lt": <unix_ts> } }` | Range filter against integer fields holding Unix timestamps (seconds). Source dates should be normalized in config via `{{toUnix ...}}` in `set` expressions.
|
|
739
|
+
| `date` | `{ "key": "<field>", "range": { "gte": <unix_ts>, "lt": <unix_ts> } }` | Range filter against integer fields holding Unix timestamps (seconds). Source dates should be normalized in config via `{{toUnix ...}}` in `set` expressions. Either bound optional for open-ended ranges (e.g., "after January" → `gte` only) |
|
|
708
740
|
| `number` | `{ "key": "<field>", "range": { "gte": <n>, "lte": <n> } }` | Either bound optional for open-ended ranges |
|
|
709
741
|
| `check` | `{ "key": "<field>", "match": { "value": true } }` | Boolean match |
|
|
710
742
|
| _(absent)_ | Do not use in filters | Internal bookkeeping field, not intended for search |
|
|
@@ -768,7 +800,7 @@ Use `scoreThresholds` from config (queried during orientation). Values are deplo
|
|
|
768
800
|
|
|
769
801
|
### Chunk Grouping
|
|
770
802
|
|
|
771
|
-
Multiple results with the same `file_path` are chunks of one document. Read the full file for complete context.
|
|
803
|
+
Multiple results with the same `file_path` (or, for source documents, the same `source`) are chunks of one document. Read the full file for complete context.
|
|
772
804
|
|
|
773
805
|
### Schema Lookup
|
|
774
806
|
|
|
@@ -776,27 +808,25 @@ Use `matched_rules` on results to look up applicable schemas for metadata interp
|
|
|
776
808
|
|
|
777
809
|
```
|
|
778
810
|
watcher_config: path="$.inferenceRules[?(@.name=='jira-issue')].schema"
|
|
779
|
-
resolve=["files","globals"]
|
|
780
811
|
```
|
|
781
812
|
|
|
782
813
|
### Full Context
|
|
783
814
|
|
|
784
|
-
Search gives you chunks; use `read` with `file_path` for the complete document.
|
|
815
|
+
Search gives you chunks; use `read` with `file_path` for the complete document. A source document has no file: render it with `POST /render` and `{ "source": "<ref>" }`, which retrieves it through its callback.
|
|
785
816
|
|
|
786
817
|
---
|
|
787
818
|
|
|
788
819
|
## Path Testing
|
|
789
820
|
|
|
790
|
-
When uncertain whether a file
|
|
821
|
+
When uncertain whether a file would be indexed, test it against the rules. `watcher_validate` with `testPaths` (and no `config`) runs the current rules against each path and returns `{ path, matchedRules, metadata }` per path (`error: "File not found"` when the file cannot be read):
|
|
791
822
|
|
|
792
823
|
```
|
|
793
|
-
|
|
824
|
+
watcher_validate: testPaths=["/data/tickets/PROJ-123.json"]
|
|
794
825
|
```
|
|
795
826
|
|
|
796
|
-
Or
|
|
827
|
+
Or call `POST /config/match` directly with `{ "paths": [...] }`. It returns `{ matches: [{ rules, watched }] }`, one entry per path, without reading the files:
|
|
797
828
|
|
|
798
|
-
-
|
|
799
|
-
- Empty `rules` array means no inference rules match
|
|
829
|
+
- `rules` lists the matching rule names; an empty array means no inference rules match
|
|
800
830
|
- `watched: false` means the path falls outside watch paths or is excluded by ignore patterns
|
|
801
831
|
|
|
802
832
|
---
|
|
@@ -809,31 +839,33 @@ Each inference rule has:
|
|
|
809
839
|
|
|
810
840
|
- `name` (required) — unique identifier
|
|
811
841
|
- `description` (required) — human-readable purpose
|
|
812
|
-
- `match` — JSON Schema
|
|
813
|
-
- `schema` — array of named schema references and/or inline schema objects with `set` templates
|
|
814
|
-
- `map` (optional) — named
|
|
815
|
-
- `template` (optional) — named
|
|
842
|
+
- `match` (required) — JSON Schema matched against file attributes (e.g. a picomatch `glob` on `file.path`)
|
|
843
|
+
- `schema` (optional) — array of named schema references and/or inline schema objects with `set` templates
|
|
844
|
+
- `map` (optional) — JsonMap transform (inline, named map, or `.json` file path)
|
|
845
|
+
- `template` (optional) — Handlebars template (inline, named template, or `.hbs`/`.handlebars` file path)
|
|
846
|
+
- `render` (optional) — declarative frontmatter + Markdown renderer (mutually exclusive with `template`)
|
|
847
|
+
- `renderAs` (optional) — output extension (1-10 lowercase alphanumerics); requires `template` or `render`
|
|
816
848
|
|
|
817
849
|
### Config Workflow
|
|
818
850
|
|
|
819
851
|
1. Edit config (or build partial config object)
|
|
820
852
|
2. Validate: `watcher_validate` with optional `testPaths` for dry-run preview
|
|
821
|
-
3. Apply: `watcher_config_apply` — validates, writes, triggers reindex
|
|
822
|
-
4. Monitor: `watcher_issues` for runtime
|
|
853
|
+
3. Apply: `watcher_config_apply` — validates, writes, triggers the `configWatch.reindex` reindex
|
|
854
|
+
4. Monitor: `watcher_issues` for runtime processing failures
|
|
823
855
|
|
|
824
856
|
### Reindex Concurrency
|
|
825
857
|
|
|
826
|
-
Reindex operations process files concurrently using `reindex.concurrency` (default 50). This applies to
|
|
858
|
+
Reindex operations process files and source documents concurrently using `reindex.concurrency` (default 50). This applies to every scope, to issue-source discovery, and to the stored-rule lookups of `POST /reindex` with `source`. The watcher's incremental processing (file events and source notifications) uses a separate `embedding.concurrency` setting.
|
|
827
859
|
|
|
828
|
-
Progress is reported via `watcher_status` (`reindex.filesProcessed` / `reindex.totalFiles
|
|
860
|
+
Progress is reported via `watcher_status` (`health.reindex.filesProcessed` / `health.reindex.totalFiles`, counting files plus source documents).
|
|
829
861
|
|
|
830
862
|
### When to Reindex
|
|
831
863
|
|
|
832
|
-
- **Rules scope** (`"rules"`): Changed rule matching patterns, set expressions, schema mappings. No re-embedding needed.
|
|
833
|
-
- **Full scope** (`"full"`):
|
|
834
|
-
- **Issues scope** (`"issues"`): After fixing the root cause of
|
|
835
|
-
- **Path scope** (`"path"`): Edited files in a specific directory and want
|
|
836
|
-
- **Prune scope** (`"prune"`): After changing `watch.paths`, adding gitignore rules, or discovering stale/orphaned points (e.g., indexed `node_modules`). Deletes points for out-of-scope files. Always `dryRun: true` first to preview.
|
|
864
|
+
- **Rules scope** (`"rules"`): Changed rule matching patterns, set expressions, schema mappings. No file re-embedding needed.
|
|
865
|
+
- **Full scope** (`"full"`): Added watch paths, broad schema restructuring, or source documents whose vectors must be rebuilt. Re-extracts every file (re-embedding the ones whose text to embed changed) and re-embeds every source document.
|
|
866
|
+
- **Issues scope** (`"issues"`): After fixing the root cause of processing failures (permissions, encoding, file format, a source outage). Re-processes only the failed files and source documents.
|
|
867
|
+
- **Path scope** (`"path"`): Edited files in a specific directory, or a single file looks stale, and you want them re-processed without a full reindex. A file whose text to embed is unchanged is not re-embedded.
|
|
868
|
+
- **Prune scope** (`"prune"`): After changing `watch.paths`, adding gitignore rules, or discovering stale/orphaned points (e.g., indexed `node_modules`). Deletes points for out-of-scope or deleted files. Always `dryRun: true` first to preview.
|
|
837
869
|
|
|
838
870
|
---
|
|
839
871
|
|
|
@@ -842,16 +874,26 @@ Progress is reported via `watcher_status` (`reindex.filesProcessed` / `reindex.t
|
|
|
842
874
|
### Escalation Path
|
|
843
875
|
|
|
844
876
|
1. `watcher_status` — is the service healthy? Is a reindex running? Is the initial scan still active?
|
|
845
|
-
2. `watcher_issues` —
|
|
846
|
-
3. `watcher_config` with `$.issues` — same
|
|
877
|
+
2. `watcher_issues` — which documents are failing and why?
|
|
878
|
+
3. `watcher_config` with `$.issues` — the same issue records via JSONPath
|
|
847
879
|
4. Check logs at the configured log path
|
|
848
880
|
|
|
849
881
|
### Error Categories
|
|
850
882
|
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
- `
|
|
854
|
-
- `
|
|
883
|
+
Every issue record's `type` is one of these codes:
|
|
884
|
+
|
|
885
|
+
- `type_collision` — conflicting metadata types across rules (includes `property`, `rules[]`, `types[]`)
|
|
886
|
+
- `interpolation_error` — template or `set` expression rendering failed (includes `property`, `rule`; `details` holds per-step failures)
|
|
887
|
+
- `extraction_error` — reading, rule application or chunking failed
|
|
888
|
+
- `embedding_error` — the embedding provider failed
|
|
889
|
+
- `upsert_error` — the vector store write failed
|
|
890
|
+
- `match_failed` — a source document's designated rule did not match (`details` holds the AJV errors)
|
|
891
|
+
- `rule_missing` — a source document's designated rule was not found
|
|
892
|
+
- `no_content` — nothing to embed
|
|
893
|
+
- `source_unavailable` — the source callback failed
|
|
894
|
+
- `unsupported_content_type` — the source callback returned a non-JSON body
|
|
895
|
+
|
|
896
|
+
Source-document issues always carry `rule` (the designated rule of the failed run).
|
|
855
897
|
|
|
856
898
|
**Issues are self-healing:** resolved on successful re-process. The issues file always represents the current set of unresolved problems: a live todo list.
|
|
857
899
|
|
|
@@ -874,25 +916,24 @@ The following helpers are available in every JsonMap `lib` context without any h
|
|
|
874
916
|
|
|
875
917
|
#### `fetchSiblings(filePath, options?)`
|
|
876
918
|
|
|
877
|
-
Retrieve extracted text from neighboring files in the same directory. Useful for contextual embedding — e.g., injecting surrounding email messages into a thread member's embedding for better semantic search.
|
|
919
|
+
Retrieve extracted text from neighboring files in the same directory with the same extension. Useful for contextual embedding — e.g., injecting surrounding email messages into a thread member's embedding for better semantic search.
|
|
878
920
|
|
|
879
921
|
**Parameters:**
|
|
880
922
|
|
|
881
|
-
- `filePath` (string) — the current file path (
|
|
882
|
-
- `options` (object, optional):
|
|
923
|
+
- `filePath` (string) — the current file path (in a rule's `map`, `$.input.file.path`)
|
|
924
|
+
- `options` (object, optional; JsonMap `params` are path strings, so a call from a config `map` uses the defaults):
|
|
883
925
|
- `before` (number, default 3) — number of preceding siblings to include
|
|
884
926
|
- `after` (number, default 1) — number of following siblings to include
|
|
885
927
|
- `sort` (`"name"` | `"mtime"`, default `"name"`) — sort order for determining neighbor position
|
|
886
928
|
|
|
887
|
-
**Returns:** `string[]` — extracted text from sibling files, in sort order. Files that fail extraction are silently skipped.
|
|
929
|
+
**Returns:** `string[]` — extracted text from sibling files, in sort order. Files that fail extraction are silently skipped. For a source document (a source rule's `map`) there is no file reader, so it returns `[]`.
|
|
888
930
|
|
|
889
|
-
**Example** (in a
|
|
931
|
+
**Example** (in a rule's `map`):
|
|
890
932
|
|
|
891
933
|
```json
|
|
892
934
|
{
|
|
893
935
|
"context": {
|
|
894
|
-
"$
|
|
895
|
-
"$args": ["$file_path", { "before": 2, "after": 1 }]
|
|
936
|
+
"$": { "method": "$.lib.fetchSiblings", "params": "$.input.file.path" }
|
|
896
937
|
}
|
|
897
938
|
}
|
|
898
939
|
```
|
|
@@ -903,12 +944,13 @@ Retrieve extracted text from neighboring files in the same directory. Useful for
|
|
|
903
944
|
|
|
904
945
|
Use `watcher_enrich` to tag documents after analysis (e.g., `reviewed: true`, project labels).
|
|
905
946
|
|
|
906
|
-
**Enrichments are durable.** Stored in a SQLite database (`<stateDir>/enrichments.sqlite`), enrichments survive full reindexes. When the watcher re-processes a file, enrichments are merged with inference rule output using composable semantics: scalar fields overwrite, array fields union+deduplicate.
|
|
947
|
+
**Enrichments are durable.** Stored in a SQLite database (`<stateDir>/enrichments.sqlite`, default `stateDir` `.jeeves-metadata`), enrichments survive full reindexes. Enriching a file that is not indexed yet stores the enrichment, which applies once the file is indexed. When the watcher re-processes a file, enrichments are merged with inference rule output using composable semantics: scalar fields overwrite, array fields union+deduplicate.
|
|
907
948
|
|
|
908
|
-
**Metadata is validated against the file's matched rule schemas
|
|
949
|
+
**Metadata is validated against the file's matched rule schemas** (for a source document, its designated rule's schema). Only declared property types are checked; unknown properties and `null` values pass. The tool reports a failure as `HTTP 400 invalid_request: Validation failed`; the structured `details` are in the HTTP response body:
|
|
909
950
|
|
|
910
951
|
```json
|
|
911
952
|
{
|
|
953
|
+
"code": "invalid_request",
|
|
912
954
|
"error": "Validation failed",
|
|
913
955
|
"details": [
|
|
914
956
|
{
|
|
@@ -945,37 +987,37 @@ The watcher includes built-in history and undo for your watched files. When enab
|
|
|
945
987
|
**View recent changes to a file:**
|
|
946
988
|
|
|
947
989
|
```
|
|
948
|
-
watcher_vcs_history: glob="
|
|
990
|
+
watcher_vcs_history: glob="/data/tickets/PROJ-123.json", limit=10
|
|
949
991
|
```
|
|
950
992
|
|
|
951
993
|
**See what changed between two versions:**
|
|
952
994
|
|
|
953
995
|
```
|
|
954
|
-
watcher_vcs_diff: glob="
|
|
996
|
+
watcher_vcs_diff: glob="/data/tickets/PROJ-123.json", commit="abc1234"
|
|
955
997
|
```
|
|
956
998
|
|
|
957
999
|
**Restore a file to a previous version:**
|
|
958
1000
|
|
|
959
1001
|
```
|
|
960
|
-
watcher_vcs_revert: glob="
|
|
1002
|
+
watcher_vcs_revert: glob="/data/tickets/PROJ-123.json", commit="abc1234"
|
|
961
1003
|
```
|
|
962
1004
|
|
|
963
1005
|
**View old content without restoring:**
|
|
964
1006
|
|
|
965
1007
|
```
|
|
966
|
-
watcher_vcs_show: path="
|
|
1008
|
+
watcher_vcs_show: path="/data/tickets/PROJ-123.json", commit="abc1234"
|
|
967
1009
|
```
|
|
968
1010
|
|
|
969
1011
|
**Exclude files that don't need versioning** (e.g., Jira issues that are read-only syncs):
|
|
970
1012
|
|
|
971
1013
|
```
|
|
972
|
-
watcher_vcs_exclude: glob="
|
|
1014
|
+
watcher_vcs_exclude: glob="/data/tickets/**/*.json"
|
|
973
1015
|
```
|
|
974
1016
|
|
|
975
1017
|
**Check if a file is excluded and why:**
|
|
976
1018
|
|
|
977
1019
|
```
|
|
978
|
-
watcher_vcs_check: path="
|
|
1020
|
+
watcher_vcs_check: path="/data/tickets/PROJ-123.json"
|
|
979
1021
|
```
|
|
980
1022
|
|
|
981
1023
|
### Enabling Version Tracking
|
|
@@ -988,7 +1030,7 @@ Squash retention activates by default when VCS is enabled, even without explicit
|
|
|
988
1030
|
|
|
989
1031
|
Not all watched files need version history. For example, if Jira issues are synced read-only, there's nothing to "undo." Use `watcher_vcs_exclude` to stop tracking specific paths.
|
|
990
1032
|
|
|
991
|
-
Exclusions are placed as close to the target as possible: if you exclude
|
|
1033
|
+
Exclusions are placed as close to the target as possible: if you exclude `/data/tickets/**/*.json`, the exclusion rule is written inside the `/data/tickets/` directory, not at the root. This keeps exclusions local and easy to reason about. Re-include a path by calling `watcher_vcs_exclude` with `remove: true`.
|
|
992
1034
|
|
|
993
1035
|
### Score Interpretation
|
|
994
1036
|
|
|
@@ -1012,8 +1054,8 @@ If tools are unavailable (plugin not loaded in this session):
|
|
|
1012
1054
|
|
|
1013
1055
|
**CLI Fallbacks:**
|
|
1014
1056
|
|
|
1015
|
-
- `jeeves-watcher status` — check if the service is running
|
|
1016
|
-
- `jeeves-watcher validate
|
|
1057
|
+
- `jeeves-watcher status [-p <port>]` — check if the service is running (`GET /status`)
|
|
1058
|
+
- `jeeves-watcher config validate -c <path>` — validate a config file against the schema (offline)
|
|
1017
1059
|
- Restart via NSSM (Windows) or systemctl (Linux)
|
|
1018
1060
|
|
|
1019
1061
|
---
|