@harperfast/template-react-ts-studio 1.11.3 → 1.11.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/.agents/skills/harper-best-practices/AGENTS.md +567 -490
  2. package/.agents/skills/harper-best-practices/rules/automatic-apis.md +46 -78
  3. package/.agents/skills/harper-best-practices/rules/defining-relationships.md +41 -63
  4. package/.agents/skills/harper-best-practices/rules/deploying-to-harper-fabric.md +59 -45
  5. package/.agents/skills/harper-best-practices/rules/load-env.md +24 -23
  6. package/.agents/skills/harper-best-practices/rules/programmatic-table-requests.md +62 -78
  7. package/.agents/skills/harper-best-practices/rules/querying-rest-apis.md +92 -65
  8. package/.agents/skills/harper-best-practices/rules/schema-design-tooling.md +53 -55
  9. package/.agents/skills/harper-best-practices/rules/v5-upgrade.md +98 -62
  10. package/.agents/skills/harper-best-practices/rules/vector-indexing.md +113 -42
  11. package/.agents/skills/harper-mcp/AGENTS.md +501 -0
  12. package/.agents/skills/harper-mcp/SKILL.md +91 -0
  13. package/.agents/skills/harper-mcp/rules/automatic-verb-tools.md +50 -0
  14. package/.agents/skills/harper-mcp/rules/connecting-clients.md +59 -0
  15. package/.agents/skills/harper-mcp/rules/custom-mcp-prompts.md +52 -0
  16. package/.agents/skills/harper-mcp/rules/custom-mcp-resources.md +64 -0
  17. package/.agents/skills/harper-mcp/rules/custom-mcp-tools.md +72 -0
  18. package/.agents/skills/harper-mcp/rules/durable-quotas.md +73 -0
  19. package/.agents/skills/harper-mcp/rules/enabling-mcp.md +63 -0
  20. package/.agents/skills/harper-mcp/rules/rate-limiting.md +62 -0
  21. package/.agents/skills/harper-mcp/rules/resources-surface.md +44 -0
  22. package/.agents/skills/harper-mcp/rules/security-posture.md +36 -0
  23. package/.agents/skills/harper-mcp/rules.manifest.yaml +203 -0
  24. package/agent/skills/harper-best-practices/AGENTS.md +567 -490
  25. package/agent/skills/harper-best-practices/rules/automatic-apis.md +46 -78
  26. package/agent/skills/harper-best-practices/rules/defining-relationships.md +41 -63
  27. package/agent/skills/harper-best-practices/rules/deploying-to-harper-fabric.md +59 -45
  28. package/agent/skills/harper-best-practices/rules/load-env.md +24 -23
  29. package/agent/skills/harper-best-practices/rules/programmatic-table-requests.md +62 -78
  30. package/agent/skills/harper-best-practices/rules/querying-rest-apis.md +92 -65
  31. package/agent/skills/harper-best-practices/rules/schema-design-tooling.md +53 -55
  32. package/agent/skills/harper-best-practices/rules/v5-upgrade.md +98 -62
  33. package/agent/skills/harper-best-practices/rules/vector-indexing.md +113 -42
  34. package/agent/skills/harper-mcp/AGENTS.md +501 -0
  35. package/agent/skills/harper-mcp/SKILL.md +83 -0
  36. package/agent/skills/harper-mcp/rules/automatic-verb-tools.md +50 -0
  37. package/agent/skills/harper-mcp/rules/connecting-clients.md +59 -0
  38. package/agent/skills/harper-mcp/rules/custom-mcp-prompts.md +52 -0
  39. package/agent/skills/harper-mcp/rules/custom-mcp-resources.md +64 -0
  40. package/agent/skills/harper-mcp/rules/custom-mcp-tools.md +72 -0
  41. package/agent/skills/harper-mcp/rules/durable-quotas.md +73 -0
  42. package/agent/skills/harper-mcp/rules/enabling-mcp.md +63 -0
  43. package/agent/skills/harper-mcp/rules/rate-limiting.md +62 -0
  44. package/agent/skills/harper-mcp/rules/resources-surface.md +44 -0
  45. package/agent/skills/harper-mcp/rules/security-posture.md +36 -0
  46. package/agent/skills/harper-mcp/rules.manifest.yaml +203 -0
  47. package/package.json +1 -1
  48. package/skills-lock.json +7 -1
@@ -5,8 +5,8 @@ metadata:
5
5
  mode: generate
6
6
  sources:
7
7
  - reference/v5/database/schema.md#Vector Indexing
8
- sourceCommit: 4fe4c9c95e0974eaa77032f6f10e36fbd8ec64ac
9
- inputHash: d90b1b74597d08a6
8
+ sourceCommit: 3749d0c54be457a2a65d9a63c738a5dc88989ecd
9
+ inputHash: 225b9bea420d9adc
10
10
  ---
11
11
 
12
12
  # Vector Indexing
@@ -15,11 +15,11 @@ Instructions for the agent to enable HNSW vector indexes on table fields and que
15
15
 
16
16
  ## When to Use
17
17
 
18
- Apply this rule when adding a vector similarity search capability to a Harper table — for example, storing text embeddings and querying for nearest neighbors, filtering by distance threshold, or tuning index construction and search parameters. Use it alongside [adding-tables-with-schemas.md](adding-tables-with-schemas.md) when defining the schema that hosts the vector field.
18
+ Apply this rule when adding a vector similarity search capability to a Harper table — for example, storing text embeddings and querying for nearest neighbors, filtering by distance threshold, or combining vector search with record-level access control. See [adding-tables-with-schemas.md](adding-tables-with-schemas.md) for how to define the surrounding table schema.
19
19
 
20
20
  ## How It Works
21
21
 
22
- 1. **Declare the vector index on a field**: Add `@indexed(type: "HNSW")` to a `[Float]` field inside a `@table` type. This creates an HNSW (Hierarchical Navigable Small World) index for approximate nearest-neighbor search.
22
+ 1. **Declare the vector index** on a `[Float]` field using `@indexed(type: "HNSW")`:
23
23
 
24
24
  ```graphql
25
25
  type Document @table {
@@ -28,7 +28,7 @@ Apply this rule when adding a vector similarity search capability to a Harper ta
28
28
  }
29
29
  ```
30
30
 
31
- 2. **Query by nearest neighbors using `sort`**: Call `.search()` with a `sort` descriptor that specifies the indexed `attribute` and a `target` vector. Use `limit` to cap results.
31
+ 2. **Query nearest neighbors** using the `sort` parameter with `attribute` and `target`:
32
32
 
33
33
  ```javascript
34
34
  let results = Document.search({
@@ -37,7 +37,7 @@ Apply this rule when adding a vector similarity search capability to a Harper ta
37
37
  });
38
38
  ```
39
39
 
40
- 3. **Combine with filter conditions**: Add a `conditions` array alongside `sort` to pre-filter records before ranking by similarity.
40
+ 3. **Combine with filter conditions** to narrow results before or during traversal:
41
41
 
42
42
  ```javascript
43
43
  let results = Document.search({
@@ -47,7 +47,25 @@ Apply this rule when adding a vector similarity search capability to a Harper ta
47
47
  });
48
48
  ```
49
49
 
50
- 4. **Filter by distance threshold**: To return only records within a similarity cutoff (without ranking), place `target` directly on the condition alongside `comparator` and `value`. This bounds result quality rather than ranking by similarity.
50
+ Conditions are evaluated _during_ graph traversal (predicate-aware search), not after. Very selective conditions are automatically diverted to an exact-scan strategy.
51
+
52
+ 4. **Use a `vectorFilter` function** for predicates not expressible as conditions (JavaScript API only):
53
+
54
+ ```javascript
55
+ let results = Document.search(
56
+ {
57
+ sort: { attribute: 'textEmbeddings', target: searchVector },
58
+ vectorFilter: (record) =>
59
+ record.tenantId === context.user.tenantId && record.status === 'published',
60
+ limit: 10,
61
+ },
62
+ context,
63
+ );
64
+ ```
65
+
66
+ The function receives a frozen candidate record and must return a boolean synchronously. It must be side-effect free and fast — it can run once per candidate visited during traversal (verdicts are memoized per query).
67
+
68
+ 5. **Filter by distance threshold** using `target` on a condition instead of `sort`:
51
69
 
52
70
  ```javascript
53
71
  let results = Document.search({
@@ -60,7 +78,7 @@ Apply this rule when adding a vector similarity search capability to a Harper ta
60
78
  });
61
79
  ```
62
80
 
63
- 5. **Include computed distance in results**: Use the special `$distance` field in `select` to return the distance from the target vector. Available in both `sort`-based and threshold-based queries.
81
+ 6. **Include computed distance in results** using the `$distance` field in `select`:
64
82
 
65
83
  ```javascript
66
84
  let results = Document.search({
@@ -70,7 +88,9 @@ Apply this rule when adding a vector similarity search capability to a Harper ta
70
88
  });
71
89
  ```
72
90
 
73
- 6. **Tune per-query search options**: Pass `distance` and `ef` directly on the `sort` descriptor to override index defaults for a single query.
91
+ `$distance` works in both `sort`-based and threshold-based queries.
92
+
93
+ 7. **Override the distance function or exploration budget per query** via options on the `sort` descriptor:
74
94
 
75
95
  ```javascript
76
96
  let results = Document.search({
@@ -79,31 +99,76 @@ Apply this rule when adding a vector similarity search capability to a Harper ta
79
99
  });
80
100
  ```
81
101
 
82
- - `distance` — overrides the distance function for this query: `"cosine"`, `"euclidean"`, or `"dotProduct"`.
83
- - `ef` — overrides the search exploration budget. Higher values improve recall at the cost of latency.
102
+ - `distance` — `"cosine"`, `"euclidean"`, or `"dotProduct"`.
103
+ - `ef` — overrides the search exploration budget for this query. Higher values improve recall at the cost of latency.
84
104
 
85
- 7. **Configure HNSW index parameters**: Pass parameters directly in the `@indexed` directive. Structural parameters (`distance`, `M`, `efConstruction`, `quantization`) trigger an index rebuild when changed; `efConstructionSearch` does not.
105
+ 8. **Tune filtered traversal** when a `vectorFilter` is very selective by raising `ef` or `filterExpansion`:
86
106
 
87
- ```graphql
88
- type Document @table {
89
- id: Long @primaryKey
90
- textEmbeddings: [Float]
91
- @indexed(type: "HNSW", distance: "euclidean", optimizeRouting: 0, efConstructionSearch: 100)
92
- }
107
+ ```javascript
108
+ let results = Document.search(
109
+ {
110
+ sort: { attribute: 'textEmbeddings', target: searchVector, ef: 200, filterExpansion: 40 },
111
+ vectorFilter: (record) => record.category === 'rare',
112
+ limit: 10,
113
+ },
114
+ context,
115
+ );
93
116
  ```
94
117
 
95
- 8. **Enable vector quantization**: Use `quantization: "int8"` to store vectors as 8-bit integers, reducing index size and memory usage. Harper re-ranks nearest-neighbor `sort` results against full-precision vectors automatically.
118
+ Filtered traversal visits at most `ef * filterExpansion` nodes (`filterExpansion` defaults to `24`). If the budget is exhausted before results fill, the search returns what was found rather than erroring.
119
+
120
+ 9. **Configure HNSW index parameters** directly on the directive:
96
121
 
97
122
  ```graphql
98
123
  type Document @table {
99
124
  id: Long @primaryKey
100
- textEmbeddings: [Float] @indexed(type: "HNSW", quantization: "int8")
125
+ textEmbeddings: [Float]
126
+ @indexed(type: "HNSW", distance: "euclidean", optimizeRouting: 0, efConstructionSearch: 100)
101
127
  }
102
128
  ```
103
129
 
130
+ | Parameter | Default | Description |
131
+ | ---------------------- | ----------------- | ------------------------------------------------------------------------------------------------ |
132
+ | `distance` | `"cosine"` | Distance function: `"cosine"`, `"euclidean"`, or `"dotProduct"` |
133
+ | `efConstruction` | `100` | Max nodes explored during index construction. Higher = better recall, lower = better performance |
134
+ | `M` | `16` | Preferred connections per graph layer |
135
+ | `optimizeRouting` | `0.5` | Heuristic aggressiveness for omitting redundant connections (0 = off, 1 = most aggressive) |
136
+ | `mL` | computed from `M` | Normalization factor for level generation |
137
+ | `efConstructionSearch` | auto-scaled | Max nodes explored during search. When unset, auto-scales with index size |
138
+ | `quantization` | — | `"int8"` stores vectors quantized to int8 |
139
+ | `filterExpansion` | `24` | Visit-budget multiplier for filtered search |
140
+
141
+ Changing `efConstructionSearch` on an existing index does not trigger a rebuild. Changing structural parameters (`distance`, `M`, `efConstruction`, `quantization`) does rebuild the index.
142
+
143
+ 10. **Enable int8 quantization** to reduce index size and memory usage:
144
+
145
+ ```graphql
146
+ type Document @table {
147
+ id: Long @primaryKey
148
+ textEmbeddings: [Float] @indexed(type: "HNSW", quantization: "int8")
149
+ }
150
+ ```
151
+
152
+ Graph navigation uses quantized distances. For `sort` queries, Harper re-ranks results against full-precision vectors, restoring exact ordering and exact `$distance` values. Distance-threshold queries filter on the approximate distance.
153
+
154
+ 11. **Implement record-level access control** by overriding `allowRead(user, target, context)` on the table resource. During vector queries the check participates in graph traversal, so a restricted user receives the k nearest records they are allowed to see:
155
+
156
+ ```javascript
157
+ export class Reports extends tables.Reports {
158
+ allowRead(user, target, context) {
159
+ if (!super.allowRead(user, target, context)) return false;
160
+ if (user.role.permission.super_user) return true;
161
+ if (this.ownerId == null) return true;
162
+ return this.ownerId === user.id;
163
+ }
164
+ }
165
+ ```
166
+
167
+ The check must be synchronous, side-effect free, and fast. `this` is the frozen record during per-record evaluation. A thrown exception denies that record (fail closed).
168
+
104
169
  ## Examples
105
170
 
106
- Full schema with custom HNSW parameters and a nearest-neighbor query with distance output:
171
+ **Full schema with custom HNSW parameters:**
107
172
 
108
173
  ```graphql
109
174
  type Document @table {
@@ -113,16 +178,33 @@ type Document @table {
113
178
  }
114
179
  ```
115
180
 
181
+ **Nearest-neighbor search with distance output:**
182
+
116
183
  ```javascript
117
- // Nearest-neighbor search with distance scores
118
184
  let results = Document.search({
119
185
  select: ['name', '$distance'],
120
186
  sort: { attribute: 'textEmbeddings', target: searchVector },
121
187
  limit: 5,
122
188
  });
189
+ ```
190
+
191
+ **Filtered vector search with tuned traversal budget:**
123
192
 
124
- // Distance-threshold query (no ranking)
125
- let closeMatches = Document.search({
193
+ ```javascript
194
+ let results = Document.search(
195
+ {
196
+ sort: { attribute: 'textEmbeddings', target: searchVector, ef: 200, filterExpansion: 40 },
197
+ vectorFilter: (record) => record.category === 'rare',
198
+ limit: 10,
199
+ },
200
+ context,
201
+ );
202
+ ```
203
+
204
+ **Distance threshold query (no ranking, cutoff only):**
205
+
206
+ ```javascript
207
+ let results = Document.search({
126
208
  conditions: {
127
209
  attribute: 'textEmbeddings',
128
210
  comparator: 'lt',
@@ -134,21 +216,10 @@ let closeMatches = Document.search({
134
216
 
135
217
  ## Notes
136
218
 
137
- ### HNSW Parameters
138
-
139
- | Parameter | Default | Description |
140
- | ---------------------- | ----------------- | ------------------------------------------------------------------------------------------------------ |
141
- | `distance` | `"cosine"` | Distance function: `"cosine"`, `"euclidean"`, or `"dotProduct"` |
142
- | `efConstruction` | `100` | Max nodes explored during index construction. Higher = better recall, lower = better performance |
143
- | `M` | `16` | Preferred connections per graph layer. Higher = more space, better recall for high-dimensional data |
144
- | `optimizeRouting` | `0.5` | Heuristic aggressiveness for omitting redundant connections (0 = off, 1 = most aggressive) |
145
- | `mL` | computed from `M` | Normalization factor for level generation |
146
- | `efConstructionSearch` | auto-scaled | Max nodes explored during search. When unset, auto-scales with index size; setting it fixes the budget |
147
- | `quantization` | — | `"int8"` stores vectors quantized to int8 |
148
-
149
- - The `distance` option on a per-query `sort` descriptor accepts `"cosine"`, `"euclidean"`, or `"dotProduct"`.
150
- - When no `ef` is passed and `efConstructionSearch` (or `efConstruction`) is not explicitly set on the index, the search budget auto-scales with index size.
151
- - `efConstruction` seeds the initial value of `efConstructionSearch`; setting either one fixes the search budget.
152
- - The correct parameter name is `efConstructionSearch` (not `efSearchConstruction`).
153
- - `$distance` is available in both `sort`-based ranking and `conditions`-based threshold queries.
154
- - For `quantization: "int8"`, distance-threshold (`lt`/`le`) queries filter on approximate distance; `sort` queries re-rank against full-precision vectors.
219
+ - Use `@indexed(type: "HNSW")` on a `[Float]` field — not on scalar fields.
220
+ - The default `distance` is `"cosine"`. Override it per-index via the directive or per-query via the `sort` descriptor.
221
+ - `efConstruction` seeds the initial value of `efConstructionSearch`. When neither is set, the search budget auto-scales with index size.
222
+ - `vectorFilter` is available from the JavaScript API only; it cannot be expressed in a REST query string.
223
+ - The parameter name Harper reads is `efConstructionSearch` (not `efSearchConstruction`).
224
+ - `$distance` must be listed explicitly in `select` to appear in results.
225
+ - For record-level `allowRead` overrides: collection-scope calls (where `this.ownerId` is `null`) should return `true` to open the connection; per-record filtering happens during query execution and event delivery.