@karmaniverous/jeeves-watcher-openclaw 0.1.2 → 0.2.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/dist/index.js CHANGED
@@ -22,6 +22,30 @@ function fail(error) {
22
22
  isError: true,
23
23
  };
24
24
  }
25
+ /** Format a connection error with actionable guidance. */
26
+ function connectionFail(error, baseUrl) {
27
+ const cause = error instanceof Error ? error.cause : undefined;
28
+ const code = cause && typeof cause === 'object' && 'code' in cause
29
+ ? String(cause.code)
30
+ : '';
31
+ const isConnectionError = code === 'ECONNREFUSED' || code === 'ENOTFOUND' || code === 'ETIMEDOUT';
32
+ if (isConnectionError) {
33
+ return {
34
+ content: [
35
+ {
36
+ type: 'text',
37
+ text: [
38
+ `Watcher service not reachable at ${baseUrl}.`,
39
+ 'Either start the watcher service, or if it runs on a different port,',
40
+ 'set plugins.entries.jeeves-watcher.config.apiUrl in openclaw.json.',
41
+ ].join('\n'),
42
+ },
43
+ ],
44
+ isError: true,
45
+ };
46
+ }
47
+ return fail(error);
48
+ }
25
49
  /** Fetch JSON from a URL, throwing on non-OK responses. */
26
50
  async function fetchJson(url, init) {
27
51
  const res = await fetch(url, init);
@@ -47,7 +71,7 @@ function register(api) {
47
71
  return ok(await fetchJson(`${baseUrl}/status`));
48
72
  }
49
73
  catch (error) {
50
- return fail(error);
74
+ return connectionFail(error, baseUrl);
51
75
  }
52
76
  },
53
77
  }, { optional: true });
@@ -89,7 +113,7 @@ function register(api) {
89
113
  }));
90
114
  }
91
115
  catch (error) {
92
- return fail(error);
116
+ return connectionFail(error, baseUrl);
93
117
  }
94
118
  },
95
119
  }, { optional: true });
@@ -122,7 +146,7 @@ function register(api) {
122
146
  }));
123
147
  }
124
148
  catch (error) {
125
- return fail(error);
149
+ return connectionFail(error, baseUrl);
126
150
  }
127
151
  },
128
152
  }, { optional: true });
@@ -156,7 +180,7 @@ function register(api) {
156
180
  }));
157
181
  }
158
182
  catch (error) {
159
- return fail(error);
183
+ return connectionFail(error, baseUrl);
160
184
  }
161
185
  },
162
186
  }, { optional: true });
@@ -191,7 +215,7 @@ function register(api) {
191
215
  }));
192
216
  }
193
217
  catch (error) {
194
- return fail(error);
218
+ return connectionFail(error, baseUrl);
195
219
  }
196
220
  },
197
221
  }, { optional: true });
@@ -217,7 +241,7 @@ function register(api) {
217
241
  }));
218
242
  }
219
243
  catch (error) {
220
- return fail(error);
244
+ return connectionFail(error, baseUrl);
221
245
  }
222
246
  },
223
247
  }, { optional: true });
@@ -245,7 +269,7 @@ function register(api) {
245
269
  }));
246
270
  }
247
271
  catch (error) {
248
- return fail(error);
272
+ return connectionFail(error, baseUrl);
249
273
  }
250
274
  },
251
275
  }, { optional: true });
@@ -258,7 +282,7 @@ function register(api) {
258
282
  return ok(await fetchJson(`${baseUrl}/issues`));
259
283
  }
260
284
  catch (error) {
261
- return fail(error);
285
+ return connectionFail(error, baseUrl);
262
286
  }
263
287
  },
264
288
  }, { optional: true });
@@ -1,5 +1,5 @@
1
1
  /**
2
2
  * @module scripts/build-skills
3
- * Compiles SKILL.src.md files with Handlebars partials into dist/skills/.
3
+ * Copies skill files to dist/skills/ for plugin packaging.
4
4
  */
5
5
  export {};
@@ -3,11 +3,51 @@ name: jeeves-watcher
3
3
  description: >
4
4
  Semantic search across a structured document archive. Use when you need to
5
5
  recall prior context, find documents, answer questions that require searching
6
- across domains (email, Slack, Jira, codebase, meetings, projects), or enrich
7
- document metadata.
6
+ across domains (email, Slack, Jira, codebase, meetings, projects), enrich
7
+ document metadata, manage watcher config, or diagnose indexing issues.
8
8
  ---
9
9
 
10
- # jeeves-watcher — Search & Discovery
10
+ # jeeves-watcher — Search, Discovery & Administration
11
+
12
+ ## Service Architecture
13
+
14
+ The watcher is an HTTP API running as a background service (typically NSSM on Windows, systemd on Linux).
15
+
16
+ **Default port:** 3458 (configurable via `api.port` in watcher config)
17
+ **Non-default port:** If the watcher runs on a different port, the user must set `plugins.entries.jeeves-watcher.config.apiUrl` in `openclaw.json`. The plugin cannot auto-discover a non-default port.
18
+
19
+ **Health check:** `GET /status` returns uptime, point count, collection dimensions, and reindex status.
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 3458; check `plugins.entries.jeeves-watcher.config.apiUrl` in `openclaw.json` if overridden):
22
+
23
+ ```
24
+ # Health check
25
+ curl http://127.0.0.1:<PORT>/status
26
+
27
+ # Search
28
+ curl -X POST http://127.0.0.1:<PORT>/search \
29
+ -H "Content-Type: application/json" \
30
+ -d '{"query": "search text", "limit": 5}'
31
+
32
+ # Query config
33
+ curl -X POST http://127.0.0.1:<PORT>/config/query \
34
+ -H "Content-Type: application/json" \
35
+ -d '{"path": "$.inferenceRules[*].name"}'
36
+ ```
37
+
38
+ **Key endpoints:**
39
+ | Endpoint | Method | Purpose |
40
+ |----------|--------|---------|
41
+ | `/status` | GET | Health check, uptime, collection stats |
42
+ | `/search` | POST | Semantic search (main query interface) |
43
+ | `/config/query` | POST | JSONPath query over merged virtual document |
44
+ | `/config/validate` | POST | Validate candidate config |
45
+ | `/config/apply` | POST | Apply config changes |
46
+ | `/config-reindex` | POST | Trigger reindex |
47
+ | `/metadata` | POST | Enrich document metadata |
48
+ | `/issues` | GET | Runtime embedding failures |
49
+
50
+ **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.
11
51
 
12
52
  ## Theory of Operation
13
53
 
@@ -37,9 +77,9 @@ You don't need to know the rules in advance. The config is introspectable at run
37
77
 
38
78
  ## Quick Start
39
79
 
40
- 1. **Orient yourself** (once per session) — learn the deployment's organizational strategy and available record types
41
- 2. **Search** — semantic search with optional metadata filters
42
- 3. **Read source** — retrieve full file content for complete context
80
+ 1. **Orient yourself** (once per session) — use `watcher_query` to learn the deployment's organizational strategy and available record types (see Orientation Pattern below)
81
+ 2. **Search** — use `watcher_search` with a natural language query and optional metadata filters
82
+ 3. **Read source** — use `read` (standard file read) with `file_path` from search results for full document content
43
83
 
44
84
  ## Tools
45
85
 
@@ -63,6 +103,28 @@ Query the merged virtual document via JSONPath.
63
103
  - `path` (string, required) — JSONPath expression
64
104
  - `resolve` (string[], optional) — `["files"]`, `["globals"]`, or `["files","globals"]`
65
105
 
106
+ ### `watcher_validate`
107
+ Validate config and optionally test file paths.
108
+ - `config` (object, optional) — candidate config (partial or full). Omit to validate current config.
109
+ - `testPaths` (string[], optional) — file paths to test against the config
110
+
111
+ Partial configs merge with current config by rule name. If `config` is omitted, tests against the running config.
112
+
113
+ ### `watcher_config_apply`
114
+ Apply config changes atomically.
115
+ - `config` (object, required) — full or partial config to apply
116
+
117
+ Validates, writes to disk, and triggers configured reindex behavior. Returns validation errors if invalid.
118
+
119
+ ### `watcher_reindex`
120
+ Trigger a reindex.
121
+ - `scope` (string, optional) — `"rules"` (default) or `"full"`
122
+
123
+ Rules scope re-applies inference rules without re-embedding (lightweight). Full scope re-processes all files.
124
+
125
+ ### `watcher_issues`
126
+ Get runtime embedding failures. Returns `{ filePath: IssueRecord }` showing files that failed and why.
127
+
66
128
  ## Qdrant Filter Syntax
67
129
 
68
130
  Filters use Qdrant's native JSON filter format, passed as the `filter` parameter to `watcher_search`.
@@ -135,45 +197,6 @@ Each result from `watcher_search` contains:
135
197
 
136
198
  Additional metadata fields depend on the deployment's inference rules (e.g., `domain`, `status`, `author`). Use `watcher_query` to discover available fields.
137
199
 
138
- ## JSONPath Patterns for Schema Discovery
139
-
140
- Use `watcher_query` to explore the merged virtual document. Common patterns:
141
-
142
- ### Orientation
143
- ```
144
- $.inferenceRules[*].['name','description'] — List all rules with descriptions
145
- $.search.scoreThresholds — Score interpretation thresholds
146
- $.slots — Named filter patterns (e.g., memory)
147
- ```
148
-
149
- ### Schema Discovery
150
- ```
151
- $.inferenceRules[?(@.name=='jira-issue')] — Full rule details
152
- $.inferenceRules[?(@.name=='jira-issue')].values — Distinct values for a rule
153
- $.inferenceRules[?(@.name=='jira-issue')].values.status — Values for a specific field
154
- ```
155
-
156
- ### Helper Enumeration
157
- ```
158
- $.mapHelpers — All JsonMap helper namespaces
159
- $.mapHelpers.slack.exports — Exports from the 'slack' helper
160
- $.templateHelpers — All Handlebars helper namespaces
161
- ```
162
-
163
- ### Issues
164
- ```
165
- $.issues — All runtime embedding failures
166
- ```
167
-
168
- ### Full Config Introspection
169
- ```
170
- $.schemas — Global named schemas
171
- $.maps — Named JsonMap transforms
172
- $.templates — Named Handlebars templates
173
- ```
174
-
175
- ---
176
-
177
200
  ## Orientation Pattern (Once Per Session)
178
201
 
179
202
  Query the deployment's organizational context and available record types. This information is stable within a session; query once and rely on results for the remainder.
@@ -223,6 +246,45 @@ The `resolve` parameter controls which reference layers are expanded in `watcher
223
246
 
224
247
  ---
225
248
 
249
+ ## JSONPath Patterns for Schema Discovery
250
+
251
+ Use `watcher_query` to explore the merged virtual document. Common patterns:
252
+
253
+ ### Orientation
254
+ ```
255
+ $.inferenceRules[*].['name','description'] — List all rules with descriptions
256
+ $.search.scoreThresholds — Score interpretation thresholds
257
+ $.slots — Named filter patterns (e.g., memory)
258
+ ```
259
+
260
+ ### Schema Discovery
261
+ ```
262
+ $.inferenceRules[?(@.name=='jira-issue')] — Full rule details
263
+ $.inferenceRules[?(@.name=='jira-issue')].values — Distinct values for a rule
264
+ $.inferenceRules[?(@.name=='jira-issue')].values.status — Values for a specific field
265
+ ```
266
+
267
+ ### Helper Enumeration
268
+ ```
269
+ $.mapHelpers — All JsonMap helper namespaces
270
+ $.mapHelpers.slack.exports — Exports from the 'slack' helper
271
+ $.templateHelpers — All Handlebars helper namespaces
272
+ ```
273
+
274
+ ### Issues
275
+ ```
276
+ $.issues — All runtime embedding failures
277
+ ```
278
+
279
+ ### Full Config Introspection
280
+ ```
281
+ $.schemas — Global named schemas
282
+ $.maps — Named JsonMap transforms
283
+ $.templates — Named Handlebars templates
284
+ ```
285
+
286
+ ---
287
+
226
288
  ## Query Planning (Per Search Task)
227
289
 
228
290
  Identify relevant rule(s) from the orientation model, then retrieve their schemas:
@@ -246,7 +308,7 @@ Retrieves valid filter values from the runtime values index (distinct values acc
246
308
 
247
309
  ---
248
310
 
249
- ## uiHint → Qdrant Filter Mapping
311
+ ## uiHint → Filter Mapping
250
312
 
251
313
  Use `uiHint` to determine filter construction strategy. **This table is explicit, not intuited:**
252
314
 
@@ -307,38 +369,6 @@ A consuming UI will necessarily compose simple single-field filters. The assista
307
369
 
308
370
  ---
309
371
 
310
- ## Search Result Shape
311
-
312
- **Qdrant output (stable across all configs):**
313
- ```json
314
- {
315
- "id": "<point_id>",
316
- "score": 0.82,
317
- "payload": {
318
- "file_path": "j:/domains/jira/VCN/issue/WEB-123.json",
319
- "chunk_index": 0,
320
- "total_chunks": 1,
321
- "chunk_text": "...",
322
- "content_hash": "...",
323
- "matched_rules": ["jira-issue", "json-subject"],
324
- ...config-defined metadata fields...
325
- }
326
- }
327
- ```
328
-
329
- **System fields present on every result** (watcher-managed, not config-defined):
330
- - `file_path` — source file path
331
- - `chunk_index` / `total_chunks` — chunk position within document
332
- - `chunk_text` — the embedded text content
333
- - `content_hash` — content fingerprint for deduplication
334
- - `matched_rules` — inference rules that produced this point's metadata
335
-
336
- **All other payload fields are config-defined** (via inference rule schemas).
337
-
338
- Refer to Qdrant documentation for the complete search response envelope.
339
-
340
- ---
341
-
342
372
  ## Post-Processing Guidance
343
373
 
344
374
  ### Score Interpretation
@@ -376,18 +406,56 @@ Or check if a specific path would match:
376
406
 
377
407
  ---
378
408
 
409
+ ## Config Authoring
410
+
411
+ ### Rule Structure
412
+ Each inference rule has:
413
+ - `name` (required) — unique identifier
414
+ - `description` (optional) — human-readable purpose
415
+ - `match` — JSON Schema with picomatch glob for path matching
416
+ - `set` — metadata fields to set on match
417
+ - `map` (optional) — named JsonMap transform
418
+ - `template` (optional) — named Handlebars template
419
+
420
+ ### Config Workflow
421
+ 1. Edit config (or build partial config object)
422
+ 2. Validate: `watcher_validate` with optional `testPaths` for dry-run preview
423
+ 3. Apply: `watcher_config_apply` — validates, writes, triggers reindex
424
+ 4. Monitor: `watcher_issues` for runtime embedding failures
425
+
426
+ ### When to Reindex
427
+ - **Rules scope** (`"rules"`): Changed rule matching patterns, set expressions, schema mappings. No re-embedding needed.
428
+ - **Full scope** (`"full"`): Changed embedding config, added watch paths, broad schema restructuring. Re-embeds everything.
429
+
430
+ ---
431
+
379
432
  ## Diagnostics
380
433
 
381
- Check the issues endpoint for failed embeddings:
382
- ```
383
- watcher_query: path="$.issues"
384
- ```
434
+ ### Escalation Path
435
+ 1. `watcher_status` — is the service healthy? Is a reindex running?
436
+ 2. `watcher_issues` — what files are failing and why?
437
+ 3. `watcher_query` with `$.issues` — same data via JSONPath
438
+ 4. Check logs at the configured log path
439
+
440
+ ### Error Categories
441
+ - `type_collision` — metadata field type mismatch during extraction (includes `property`, `rules[]`, `types[]`)
442
+ - `interpolation` / `interpolation_error` — template/set expression failed to resolve (includes `property`, `rule`)
443
+ - `read_failure` — file couldn't be read (permissions, encoding)
444
+ - `embedding` — embedding API error
385
445
 
386
446
  **Issues are self-healing:** resolved on successful re-process. The issues file always represents the current set of unresolved problems: a live todo list.
387
447
 
388
- **Issue types:**
389
- - `type_collision` — multiple rules declare the same property with incompatible types (includes `property`, `rules[]`, `types[]`)
390
- - `interpolation_error` — `set` template path doesn't resolve (includes `property`, `rule`)
448
+ ---
449
+
450
+ ## Helper Management
451
+
452
+ Helpers use namespace prefixing: config key becomes prefix. A helper named `slack` exports `slack_extractParticipants`.
453
+
454
+ Enumerate loaded helpers:
455
+ ```
456
+ $.mapHelpers — JsonMap helper namespaces with exports
457
+ $.templateHelpers — Handlebars helper namespaces with exports
458
+ ```
391
459
 
392
460
  ---
393
461
 
@@ -420,6 +488,16 @@ If the watcher is unreachable:
420
488
  - Fall back to direct `read` for known file paths
421
489
  - Do not retry silently in a loop
422
490
 
491
+ If tools are unavailable (plugin not loaded in this session):
492
+ - The watcher API is still accessible via direct HTTP calls
493
+ - Use `exec` to call the endpoints listed in Service Architecture
494
+ - Default: `http://127.0.0.1:3458`
495
+
496
+ **CLI Fallbacks:**
497
+ - `jeeves-watcher status` — check if the service is running
498
+ - `jeeves-watcher validate` — validate config from CLI
499
+ - Restart via NSSM (Windows) or systemctl (Linux)
500
+
423
501
  ---
424
502
 
425
503
  ## References
@@ -34,5 +34,7 @@ export declare function getApiUrl(api: PluginApi): string;
34
34
  export declare function ok(data: unknown): ToolResult;
35
35
  /** Format an error tool result. */
36
36
  export declare function fail(error: unknown): ToolResult;
37
+ /** Format a connection error with actionable guidance. */
38
+ export declare function connectionFail(error: unknown, baseUrl: string): ToolResult;
37
39
  /** Fetch JSON from a URL, throwing on non-OK responses. */
38
40
  export declare function fetchJson(url: string, init?: RequestInit): Promise<unknown>;
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "id": "jeeves-watcher-openclaw",
3
3
  "name": "Jeeves Watcher",
4
- "description": "Semantic search and metadata enrichment via a jeeves-watcher instance.",
5
- "version": "0.1.2",
4
+ "description": "Semantic search, metadata enrichment, and instance administration for a jeeves-watcher deployment.",
5
+ "version": "0.2.0",
6
6
  "skills": [
7
- "dist/skills/jeeves-watcher",
8
- "dist/skills/jeeves-watcher-admin"
7
+ "dist/skills/jeeves-watcher"
9
8
  ],
10
9
  "configSchema": {
11
10
  "type": "object",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@karmaniverous/jeeves-watcher-openclaw",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "author": "Jason Williscroft",
5
5
  "description": "OpenClaw plugin for jeeves-watcher — semantic search and metadata enrichment tools",
6
6
  "license": "BSD-3-Clause",
@@ -59,7 +59,6 @@
59
59
  "@rollup/plugin-typescript": "^12.3.0",
60
60
  "auto-changelog": "^2.5.0",
61
61
  "cross-env": "^10.1.0",
62
- "handlebars": "^4.7.8",
63
62
  "release-it": "^19.2.4",
64
63
  "rollup": "^4.59.0",
65
64
  "tslib": "^2.8.1"
@@ -1,200 +0,0 @@
1
- ---
2
- name: jeeves-watcher-admin
3
- description: >
4
- Instance management for a jeeves-watcher deployment. Use when you need to
5
- author or validate config, trigger reindexing, diagnose embedding failures,
6
- or manage helper registrations.
7
- ---
8
-
9
- # jeeves-watcher — Instance Administration
10
-
11
- ## Tools
12
-
13
- ### `watcher_validate`
14
- Validate config and optionally test file paths.
15
- - `config` (object, optional) — candidate config (partial or full). Omit to validate current config.
16
- - `testPaths` (string[], optional) — file paths to test against the config
17
-
18
- Partial configs merge with current config by rule name. If `config` is omitted, tests against the running config.
19
-
20
- ### `watcher_config_apply`
21
- Apply config changes atomically.
22
- - `config` (object, required) — full or partial config to apply
23
-
24
- Validates, writes to disk, and triggers configured reindex behavior. Returns validation errors if invalid.
25
-
26
- ### `watcher_reindex`
27
- Trigger a reindex.
28
- - `scope` (string, optional) — `"rules"` (default) or `"full"`
29
-
30
- Rules scope re-applies inference rules without re-embedding (lightweight). Full scope re-processes all files.
31
-
32
- ### `watcher_issues`
33
- Get runtime embedding failures. Returns `{ filePath: IssueRecord }` showing files that failed and why.
34
-
35
- ### `watcher_query`
36
- Query config and runtime state via JSONPath (same tool as consumer skill).
37
-
38
- ### `watcher_status`
39
- Service health check including reindex progress.
40
-
41
- ## Qdrant Filter Syntax
42
-
43
- Filters use Qdrant's native JSON filter format, passed as the `filter` parameter to `watcher_search`.
44
-
45
- ### Basic Patterns
46
-
47
- **Match exact value:**
48
- ```json
49
- { "must": [{ "key": "domain", "match": { "value": "email" } }] }
50
- ```
51
-
52
- **Match text (full-text search within field):**
53
- ```json
54
- { "must": [{ "key": "chunk_text", "match": { "text": "authentication" } }] }
55
- ```
56
-
57
- **Combine conditions (AND):**
58
- ```json
59
- {
60
- "must": [
61
- { "key": "domain", "match": { "value": "jira" } },
62
- { "key": "status", "match": { "value": "In Progress" } }
63
- ]
64
- }
65
- ```
66
-
67
- **Exclude (NOT):**
68
- ```json
69
- {
70
- "must_not": [{ "key": "domain", "match": { "value": "repos" } }]
71
- }
72
- ```
73
-
74
- **Any of (OR):**
75
- ```json
76
- {
77
- "should": [
78
- { "key": "domain", "match": { "value": "email" } },
79
- { "key": "domain", "match": { "value": "slack" } }
80
- ]
81
- }
82
- ```
83
-
84
- **Nested (combine AND + NOT):**
85
- ```json
86
- {
87
- "must": [{ "key": "domain", "match": { "value": "jira" } }],
88
- "must_not": [{ "key": "status", "match": { "value": "Done" } }]
89
- }
90
- ```
91
-
92
- ### Key Differences
93
- - `match.value` — exact match (case-sensitive, for keyword fields like `domain`, `status`)
94
- - `match.text` — full-text match (for text fields like `chunk_text`)
95
-
96
- ## Search Result Shape
97
-
98
- Each result from `watcher_search` contains:
99
-
100
- | Field | Type | Description |
101
- |-------|------|-------------|
102
- | `id` | string | Qdrant point ID |
103
- | `score` | number | Similarity score (0-1, higher = more relevant) |
104
- | `payload.file_path` | string | Source file path |
105
- | `payload.chunk_text` | string | The matched text chunk |
106
- | `payload.chunk_index` | number | Chunk position within the file |
107
- | `payload.total_chunks` | number | Total chunks for this file |
108
- | `payload.content_hash` | string | Hash of the full document content |
109
- | `payload.matched_rules` | string[] | Names of inference rules that matched |
110
-
111
- Additional metadata fields depend on the deployment's inference rules (e.g., `domain`, `status`, `author`). Use `watcher_query` to discover available fields.
112
-
113
- ## JSONPath Patterns for Schema Discovery
114
-
115
- Use `watcher_query` to explore the merged virtual document. Common patterns:
116
-
117
- ### Orientation
118
- ```
119
- $.inferenceRules[*].['name','description'] — List all rules with descriptions
120
- $.search.scoreThresholds — Score interpretation thresholds
121
- $.slots — Named filter patterns (e.g., memory)
122
- ```
123
-
124
- ### Schema Discovery
125
- ```
126
- $.inferenceRules[?(@.name=='jira-issue')] — Full rule details
127
- $.inferenceRules[?(@.name=='jira-issue')].values — Distinct values for a rule
128
- $.inferenceRules[?(@.name=='jira-issue')].values.status — Values for a specific field
129
- ```
130
-
131
- ### Helper Enumeration
132
- ```
133
- $.mapHelpers — All JsonMap helper namespaces
134
- $.mapHelpers.slack.exports — Exports from the 'slack' helper
135
- $.templateHelpers — All Handlebars helper namespaces
136
- ```
137
-
138
- ### Issues
139
- ```
140
- $.issues — All runtime embedding failures
141
- ```
142
-
143
- ### Full Config Introspection
144
- ```
145
- $.schemas — Global named schemas
146
- $.maps — Named JsonMap transforms
147
- $.templates — Named Handlebars templates
148
- ```
149
-
150
- ## Config Authoring
151
-
152
- ### Rule Structure
153
- Each inference rule has:
154
- - `name` (required) — unique identifier
155
- - `description` (optional) — human-readable purpose
156
- - `match` — JSON Schema with picomatch glob for path matching
157
- - `set` — metadata fields to set on match
158
- - `map` (optional) — named JsonMap transform
159
- - `template` (optional) — named Handlebars template
160
-
161
- ### Config Workflow
162
- 1. Edit config (or build partial config object)
163
- 2. Validate: `watcher_validate` with optional `testPaths` for dry-run preview
164
- 3. Apply: `watcher_config_apply` — validates, writes, triggers reindex
165
- 4. Monitor: `watcher_issues` for runtime embedding failures
166
-
167
- ### When to Reindex
168
- - **Rules scope** (`"rules"`): Changed rule matching patterns, set expressions, schema mappings. No re-embedding needed.
169
- - **Full scope** (`"full"`): Changed embedding config, added watch paths, broad schema restructuring. Re-embeds everything.
170
-
171
- ## Diagnostics
172
-
173
- ### Escalation Path
174
- 1. `watcher_status` — is the service healthy? Is a reindex running?
175
- 2. `watcher_issues` — what files are failing and why?
176
- 3. `watcher_query` with `$.issues` — same data via JSONPath
177
- 4. Check logs at the configured log path
178
-
179
- ### Error Categories
180
- - `type_collision` — metadata field type mismatch during extraction
181
- - `interpolation` — template/set expression failed to resolve
182
- - `read_failure` — file couldn't be read (permissions, encoding)
183
- - `embedding` — embedding API error
184
-
185
- ## Helper Management
186
-
187
- Helpers use namespace prefixing: config key becomes prefix. A helper named `slack` exports `slack_extractParticipants`.
188
-
189
- Enumerate loaded helpers:
190
- ```
191
- $.mapHelpers — JsonMap helper namespaces with exports
192
- $.templateHelpers — Handlebars helper namespaces with exports
193
- ```
194
-
195
- ## CLI Fallbacks
196
-
197
- If the watcher API is down:
198
- - `jeeves-watcher status` — check if the service is running
199
- - `jeeves-watcher validate` — validate config from CLI
200
- - Restart via NSSM (Windows) or systemctl (Linux)