@gmickel/gno 1.17.0 → 1.19.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.
Files changed (167) hide show
  1. package/README.md +18 -4
  2. package/assets/skill/SKILL.md +44 -1
  3. package/assets/skill/mcp-reference.md +21 -0
  4. package/package.json +3 -2
  5. package/spec/AGENTS.md +83 -0
  6. package/spec/CLAUDE.md +83 -0
  7. package/spec/bench-fixture.schema.json +137 -0
  8. package/spec/cli.md +2894 -0
  9. package/spec/db/schema.sql +442 -0
  10. package/spec/evals-agentic.md +510 -0
  11. package/spec/evals.md +1106 -0
  12. package/spec/mcp.md +2229 -0
  13. package/spec/output-schemas/activation-verification.schema.json +515 -0
  14. package/spec/output-schemas/ask.schema.json +366 -0
  15. package/spec/output-schemas/backlinks.schema.json +131 -0
  16. package/spec/output-schemas/bench-result.schema.json +120 -0
  17. package/spec/output-schemas/capture-receipt.schema.json +143 -0
  18. package/spec/output-schemas/collection-list.schema.json +45 -0
  19. package/spec/output-schemas/context-capsule-v1.schema.json +691 -0
  20. package/spec/output-schemas/context-capsule-verification.schema.json +1338 -0
  21. package/spec/output-schemas/context-list.schema.json +21 -0
  22. package/spec/output-schemas/doctor.schema.json +313 -0
  23. package/spec/output-schemas/error.schema.json +30 -0
  24. package/spec/output-schemas/expansion.schema.json +37 -0
  25. package/spec/output-schemas/get.schema.json +140 -0
  26. package/spec/output-schemas/graph-query.schema.json +99 -0
  27. package/spec/output-schemas/graph.schema.json +371 -0
  28. package/spec/output-schemas/links-list.schema.json +186 -0
  29. package/spec/output-schemas/mcp-add-collection-result.schema.json +23 -0
  30. package/spec/output-schemas/mcp-capture-result.schema.json +152 -0
  31. package/spec/output-schemas/mcp-http-error.schema.json +30 -0
  32. package/spec/output-schemas/mcp-job-list.schema.json +58 -0
  33. package/spec/output-schemas/mcp-job-status.schema.json +224 -0
  34. package/spec/output-schemas/mcp-remove-result.schema.json +39 -0
  35. package/spec/output-schemas/mcp-sync-result.schema.json +41 -0
  36. package/spec/output-schemas/mcp-tag-result.schema.json +33 -0
  37. package/spec/output-schemas/models-list.schema.json +93 -0
  38. package/spec/output-schemas/multi-get.schema.json +103 -0
  39. package/spec/output-schemas/process-status.schema.json +119 -0
  40. package/spec/output-schemas/query-diagnose.schema.json +123 -0
  41. package/spec/output-schemas/resident-status.schema.json +154 -0
  42. package/spec/output-schemas/retrieval-trace-common.schema.json +492 -0
  43. package/spec/output-schemas/retrieval-trace-delete.schema.json +16 -0
  44. package/spec/output-schemas/retrieval-trace-export.schema.json +61 -0
  45. package/spec/output-schemas/retrieval-trace-filters.schema.json +139 -0
  46. package/spec/output-schemas/retrieval-trace-judgment.schema.json +15 -0
  47. package/spec/output-schemas/retrieval-trace-list.schema.json +18 -0
  48. package/spec/output-schemas/retrieval-trace-payloads.schema.json +178 -0
  49. package/spec/output-schemas/retrieval-trace-purge.schema.json +31 -0
  50. package/spec/output-schemas/retrieval-trace-qrels.schema.json +303 -0
  51. package/spec/output-schemas/retrieval-trace-replay.schema.json +286 -0
  52. package/spec/output-schemas/retrieval-trace-show.schema.json +69 -0
  53. package/spec/output-schemas/retrieval-trace-summary.schema.json +65 -0
  54. package/spec/output-schemas/search-result.schema.json +154 -0
  55. package/spec/output-schemas/search-results.schema.json +338 -0
  56. package/spec/output-schemas/similar.schema.json +84 -0
  57. package/spec/output-schemas/status.schema.json +676 -0
  58. package/spec/output-schemas/tags-list.schema.json +48 -0
  59. package/src/app/context-runtime-types.ts +3 -0
  60. package/src/app/context-runtime.ts +15 -1
  61. package/src/cli/commands/ask.ts +106 -36
  62. package/src/cli/commands/context-build.ts +56 -9
  63. package/src/cli/commands/daemon.ts +69 -2
  64. package/src/cli/commands/get.ts +64 -3
  65. package/src/cli/commands/models/pull.ts +13 -3
  66. package/src/cli/commands/query.ts +62 -23
  67. package/src/cli/commands/replay.ts +140 -0
  68. package/src/cli/commands/search.ts +48 -3
  69. package/src/cli/commands/shared.ts +3 -1
  70. package/src/cli/commands/status.ts +2 -0
  71. package/src/cli/commands/trace.ts +200 -0
  72. package/src/cli/commands/vsearch.ts +75 -53
  73. package/src/cli/detach.ts +37 -20
  74. package/src/cli/program.ts +329 -27
  75. package/src/config/index.ts +12 -0
  76. package/src/config/retrieval-traces.ts +56 -0
  77. package/src/config/types.ts +41 -0
  78. package/src/core/context-compiler.ts +11 -4
  79. package/src/core/job-manager.ts +19 -0
  80. package/src/core/mutation-generations.ts +33 -0
  81. package/src/core/retrieval-qrels.ts +405 -0
  82. package/src/core/retrieval-replay-candidate.ts +368 -0
  83. package/src/core/retrieval-replay-types.ts +109 -0
  84. package/src/core/retrieval-replay-validation.ts +89 -0
  85. package/src/core/retrieval-replay.ts +441 -0
  86. package/src/core/retrieval-trace-evidence-origin.ts +175 -0
  87. package/src/core/retrieval-trace-export.ts +113 -0
  88. package/src/core/retrieval-trace-filter-normalization.ts +27 -0
  89. package/src/core/retrieval-trace-filters.ts +19 -0
  90. package/src/core/retrieval-trace-management-helpers.ts +247 -0
  91. package/src/core/retrieval-trace-management-types.ts +132 -0
  92. package/src/core/retrieval-trace-management.ts +422 -0
  93. package/src/core/retrieval-trace-request.ts +141 -0
  94. package/src/core/retrieval-trace-session.ts +494 -0
  95. package/src/core/retrieval-trace.ts +472 -0
  96. package/src/llm/cache.ts +13 -3
  97. package/src/llm/nodeLlamaCpp/adapter.ts +10 -1
  98. package/src/llm/nodeLlamaCpp/lifecycle.ts +71 -0
  99. package/src/mcp/context.ts +161 -0
  100. package/src/mcp/http-security.ts +477 -0
  101. package/src/mcp/http-session.ts +272 -0
  102. package/src/mcp/http-transport.ts +370 -0
  103. package/src/mcp/resources/index.ts +141 -134
  104. package/src/mcp/server.ts +19 -79
  105. package/src/mcp/tools/add-collection.ts +3 -1
  106. package/src/mcp/tools/capture.ts +3 -0
  107. package/src/mcp/tools/clear-collection-embeddings.ts +2 -0
  108. package/src/mcp/tools/context.ts +68 -16
  109. package/src/mcp/tools/embed.ts +62 -52
  110. package/src/mcp/tools/get.ts +35 -1
  111. package/src/mcp/tools/index-cmd.ts +88 -74
  112. package/src/mcp/tools/index.ts +96 -2
  113. package/src/mcp/tools/query.ts +95 -64
  114. package/src/mcp/tools/remove-collection.ts +2 -0
  115. package/src/mcp/tools/search.ts +36 -13
  116. package/src/mcp/tools/status.ts +11 -0
  117. package/src/mcp/tools/sync.ts +16 -14
  118. package/src/mcp/tools/trace.ts +143 -0
  119. package/src/mcp/tools/vsearch.ts +71 -38
  120. package/src/mcp/tools/workspace-write.ts +7 -3
  121. package/src/pipeline/answer.ts +167 -26
  122. package/src/pipeline/graph-retrieval.ts +15 -1
  123. package/src/pipeline/hybrid.ts +151 -43
  124. package/src/pipeline/search.ts +36 -3
  125. package/src/pipeline/trace-metadata.ts +47 -0
  126. package/src/pipeline/types.ts +43 -0
  127. package/src/pipeline/vsearch.ts +101 -38
  128. package/src/sdk/client.ts +380 -71
  129. package/src/sdk/documents.ts +48 -1
  130. package/src/sdk/index.ts +17 -0
  131. package/src/sdk/types.ts +28 -0
  132. package/src/serve/background-runtime.ts +12 -212
  133. package/src/serve/context-capsule.ts +67 -8
  134. package/src/serve/embed-scheduler.ts +74 -43
  135. package/src/serve/index.ts +9 -0
  136. package/src/serve/jobs.ts +78 -80
  137. package/src/serve/public/app.tsx +12 -1
  138. package/src/serve/public/components/HealthCenter.tsx +74 -1
  139. package/src/serve/public/globals.built.css +1 -1
  140. package/src/serve/public/lib/workspace-tabs.ts +2 -0
  141. package/src/serve/public/pages/Dashboard.tsx +11 -0
  142. package/src/serve/public/pages/TraceHistory.tsx +478 -0
  143. package/src/serve/public/pages/trace-history-detail.tsx +224 -0
  144. package/src/serve/resident-admission.ts +159 -0
  145. package/src/serve/resident-background-work.ts +39 -0
  146. package/src/serve/resident-request.ts +55 -0
  147. package/src/serve/resident-runtime.ts +490 -0
  148. package/src/serve/resident-status.ts +96 -0
  149. package/src/serve/retrieval-trace.ts +28 -0
  150. package/src/serve/routes/api.ts +629 -239
  151. package/src/serve/routes/mcp.ts +69 -0
  152. package/src/serve/routes/traces.ts +156 -0
  153. package/src/serve/server.ts +276 -37
  154. package/src/serve/status-model.ts +51 -0
  155. package/src/serve/status.ts +5 -0
  156. package/src/store/index.ts +31 -0
  157. package/src/store/migrations/014-retrieval-traces.ts +303 -0
  158. package/src/store/migrations/index.ts +2 -0
  159. package/src/store/retrieval-trace-codec.ts +384 -0
  160. package/src/store/sqlite/adapter.ts +179 -10
  161. package/src/store/sqlite/retrieval-trace-management-store.ts +341 -0
  162. package/src/store/sqlite/retrieval-trace-retention.ts +349 -0
  163. package/src/store/sqlite/retrieval-trace-rows.ts +267 -0
  164. package/src/store/sqlite/retrieval-trace-store.ts +515 -0
  165. package/src/store/types.ts +297 -0
  166. package/src/store/vector/sqlite-vec.ts +76 -1
  167. package/src/store/vector/types.ts +1 -1
package/README.md CHANGED
@@ -94,7 +94,7 @@ gno daemon --detach # headless continuous indexing (background; --status / --st
94
94
 
95
95
  <!-- public-truth:current-version -->
96
96
 
97
- > Current release: **v1.16.0** — see [CHANGELOG.md](./CHANGELOG.md)
97
+ > Current release: **v1.18.0** — see [CHANGELOG.md](./CHANGELOG.md)
98
98
 
99
99
  <!-- /public-truth -->
100
100
 
@@ -104,6 +104,11 @@ gno daemon --detach # headless continuous indexing (background; --status / --st
104
104
  Web/Desktop dashboard now share a per-folder lexical retrieval proof. Local
105
105
  semantic readiness remains independent, and installed MCP targets can run an
106
106
  explicit read-only retrieval smoke from Connectors.
107
+ - **One resident gateway**: `gno serve` and `gno daemon` now host stateful
108
+ Streamable HTTP MCP at `/mcp` from the same long-lived runtime as their
109
+ watcher, jobs, stores, and models. The packed npm smoke proves two-client
110
+ parity, warm reuse, redacted lifecycle status, fail-closed security, restart,
111
+ and shutdown.
107
112
  - **Second-brain capture**: `gno capture`, REST `/api/capture`, SDK
108
113
  `client.capture()`, MCP `gno_capture`, and Web UI Quick Capture write
109
114
  provenance-rich notes from text, stdin, or files, including typed presets for
@@ -308,7 +313,7 @@ Use `gno daemon` when you want continuous indexing without the browser or
308
313
  desktop shell open.
309
314
 
310
315
  ```bash
311
- gno daemon # foreground (Ctrl+C to stop)
316
+ gno daemon # foreground + /mcp on 127.0.0.1:3000
312
317
  gno daemon --no-sync-on-start
313
318
  gno daemon --detach # background (macOS/Linux); auto-writes pid + log files
314
319
  gno daemon --status # check the detached process
@@ -548,9 +553,9 @@ Connect GNO to Claude Desktop, Cursor, Raycast, and more:
548
553
 
549
554
  ![GNO MCP](./assets/screenshots/mcp.jpg)
550
555
 
551
- GNO exposes 19 tools by default via [Model Context Protocol](https://modelcontextprotocol.io),
556
+ GNO exposes 21 tools by default via [Model Context Protocol](https://modelcontextprotocol.io),
552
557
  including the core retrieval tools below. Starting MCP with `--enable-write`
553
- adds 11 opt-in mutation tools, for 30 total.
558
+ adds 15 opt-in mutation tools, for 36 total.
554
559
 
555
560
  | Tool | Description |
556
561
  | :------------------- | :------------------------------------ |
@@ -566,11 +571,20 @@ adds 11 opt-in mutation tools, for 30 total.
566
571
  | `gno_similar` | Find semantically similar documents |
567
572
  | `gno_graph` | Get knowledge graph (nodes and edges) |
568
573
  | `gno_status` | Index health check |
574
+ | `gno_trace_list` | List private local retrieval receipts |
575
+ | `gno_trace_show` | Inspect one bounded trace receipt |
569
576
 
570
577
  **Design**: Default MCP mode is read-only: retrieval, graph, status, and job
571
578
  inspection. Your AI assistant synthesizes answers from retrieved context. Write
572
579
  tools are available only through the explicit `--enable-write` opt-in.
573
580
 
581
+ `gno serve` and `gno daemon` also expose this surface as stateful Streamable
582
+ HTTP at `http://127.0.0.1:3000/mcp`. HTTP stays read-only by default.
583
+ Authenticated non-loopback access is available through the headless daemon and
584
+ requires an explicit restrictive bearer-token file plus exact Host and Origin
585
+ allowlists; `gno serve` remains loopback-only. Authentication alone never
586
+ enables mutation tools.
587
+
574
588
  [MCP setup guide →](https://gno.sh/docs/MCP/)
575
589
 
576
590
  ---
@@ -71,8 +71,9 @@ Recipe rules:
71
71
  | **Index** | `init`, `collection add/list/remove`, `index`, `update`, `embed` | Set up and maintain document index |
72
72
  | **Tags** | `tags`, `tags add`, `tags rm` | Organize and filter documents |
73
73
  | **Context** | `context add/list/rm/check/build/verify` | Configure guidance or compile/verify evidence Capsules |
74
+ | **Traces** | `trace list/show/label/export/replay/delete/purge` | Manage and replay private retrieval receipts |
74
75
  | **Models** | `models list/use/pull/clear/path` | Manage local AI models |
75
- | **Serve** | `serve` | Web UI for browsing and searching |
76
+ | **Serve** | `serve`, `daemon` | One resident Web/headless gateway and watcher |
76
77
  | **Publish** | `publish export` | Export gno.sh publish artifacts |
77
78
  | **MCP** | `mcp`, `mcp install/uninstall/status` | AI assistant integration |
78
79
  | **Skill** | `skill install/uninstall/show/paths` | Install skill for AI agents |
@@ -155,12 +156,54 @@ gno multi-get gno://work/doc1.md gno://work/doc2.md
155
156
  # Search, get full content of top result
156
157
  gno query "auth" --json | jq -r '.results[0].uri' | xargs gno get
157
158
 
159
+ # Exclude documents containing a term
160
+ gno search "deployment" --exclude staging
161
+
158
162
  # Get all results
159
163
  gno search "error handling" --json | jq -r '.results[].uri' | xargs gno multi-get
160
164
  ```
161
165
 
166
+ When the user wants a synthesized answer instead of ranked evidence:
167
+
168
+ ```bash
169
+ gno ask "What changed in the deployment process?" --answer
170
+ ```
171
+
172
+ Trace recording is local and off by default. `metadata` mode is diagnostic-only
173
+ and omits raw query/goal/filter values; `replay` is separate explicit consent
174
+ to retain those bounded inputs under configured local retention limits. No
175
+ receipt is uploaded automatically, and disabling capture does not disable
176
+ inspection or deletion of existing receipts.
177
+
178
+ For an explicitly labeled, replay-mode receipt, export content-free qrels and
179
+ compare one candidate without changing the live ranking setup:
180
+
181
+ ```bash
182
+ gno trace export <trace-id> --format qrels --output qrels.json
183
+ gno trace replay <qrels-export-id> --candidate hybrid --md
184
+ ```
185
+
186
+ Treat replay as evidence for a human promotion decision. It always reports
187
+ `applied: false`; never claim that replay changed boosts, prompts, models,
188
+ configuration, traces, or source files.
189
+
162
190
  ## MCP Retrieval Strategy
163
191
 
192
+ For a long-lived client that supports Streamable HTTP, start one resident owner
193
+ with `gno serve` or `gno daemon` and connect to
194
+ `http://127.0.0.1:3000/mcp`. Existing installed stdio entries remain valid.
195
+ Serve is always loopback-only. Only daemon accepts an explicit non-loopback bind,
196
+ and only with a restrictive bearer-token file plus exact Host/Origin allowlists.
197
+ Authentication never enables writes by itself.
198
+
199
+ For explicit retrieval feedback, use `gno_trace_list` and `gno_trace_show` to
200
+ inspect local receipts. Never infer irrelevance from a missing click, a failed
201
+ request, or a partial/cancelled outcome. Use write-enabled
202
+ `gno_trace_label` only when the user explicitly supplies a
203
+ relevant/irrelevant/missing-expected judgment. Trace export/delete/purge are
204
+ also write tools and require separate write enablement; bearer authentication
205
+ alone is insufficient.
206
+
164
207
  When using GNO through MCP, prefer this retrieval order:
165
208
 
166
209
  1. Check `gno_status` first when freshness, missing vectors, or stale results are plausible.
@@ -72,6 +72,27 @@ Do not shorten a generated entry to `gno mcp`.
72
72
  gno mcp status
73
73
  ```
74
74
 
75
+ ## Resident Streamable HTTP
76
+
77
+ `gno serve` and `gno daemon` expose the same read-only-by-default MCP surface at
78
+ `http://127.0.0.1:3000/mcp`. Use this URL for clients that support Streamable
79
+ HTTP and benefit from shared warm stores, jobs, watchers, and model leases.
80
+ Existing `gno mcp install` stdio entries remain valid.
81
+
82
+ Only `gno daemon` supports an explicit non-loopback bind. It requires a
83
+ restrictive bearer-token file plus exact Host and Origin allowlists.
84
+ Authentication does not grant writes; `gateway.enableWrite` or
85
+ `--mcp-enable-write` is a separate opt-in. `gno serve` always remains
86
+ loopback-only.
87
+
88
+ Inspect the safe lifecycle without exposing paths or secrets:
89
+
90
+ ```bash
91
+ curl http://127.0.0.1:3000/api/resident/status
92
+ gno serve --status --json
93
+ gno daemon --status --json
94
+ ```
95
+
75
96
  ## Retrieval Order
76
97
 
77
98
  For normal questions, start with `gno_query`, then read targeted snippets with
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gmickel/gno",
3
- "version": "1.17.0",
3
+ "version": "1.19.0",
4
4
  "description": "Local semantic search for your documents. Index Markdown, PDF, and Office files with hybrid BM25 + vector search.",
5
5
  "keywords": [
6
6
  "embeddings",
@@ -28,6 +28,7 @@
28
28
  "files": [
29
29
  "assets",
30
30
  "bunfig.toml",
31
+ "spec",
31
32
  "src",
32
33
  "THIRD_PARTY_NOTICES.md",
33
34
  "vendor"
@@ -143,7 +144,7 @@
143
144
  "dependencies": {
144
145
  "@codemirror/lang-markdown": "6.5.0",
145
146
  "@codemirror/theme-one-dark": "6.1.3",
146
- "@modelcontextprotocol/sdk": "1.27.1",
147
+ "@modelcontextprotocol/sdk": "1.29.0",
147
148
  "@radix-ui/react-collapsible": "1.1.12",
148
149
  "@radix-ui/react-dialog": "1.1.15",
149
150
  "@radix-ui/react-dropdown-menu": "2.1.16",
package/spec/AGENTS.md ADDED
@@ -0,0 +1,83 @@
1
+ # Specifications
2
+
3
+ Interface contracts and schemas for GNO.
4
+
5
+ ## Structure
6
+
7
+ ```
8
+ spec/
9
+ ├── cli.md # CLI commands, flags, exit codes
10
+ ├── mcp.md # MCP tools, resources, schemas
11
+ ├── evals.md # Evaluation framework spec
12
+ ├── db/
13
+ │ └── schema.sql # Database schema
14
+ └── output-schemas/ # JSON schemas for all outputs
15
+ ├── search-results.schema.json
16
+ ├── ask.schema.json
17
+ ├── status.schema.json
18
+ └── ...
19
+ ```
20
+
21
+ ## Spec-First Workflow
22
+
23
+ When adding/modifying commands or outputs:
24
+
25
+ 1. **Update spec first** - Define the interface before implementation
26
+ 2. **Add/update JSON schema** - If output shape changes
27
+ 3. **Add contract tests** - In `test/spec/schemas/`
28
+ 4. **Implement** - Code to match spec
29
+ 5. **Verify** - `bun test` passes
30
+
31
+ ## JSON Schemas
32
+
33
+ Schemas define the structure of all JSON outputs:
34
+
35
+ - Validated by contract tests
36
+ - Used for documentation
37
+ - Enable type generation
38
+
39
+ ### Schema Naming
40
+
41
+ - `<command>.schema.json` - Single command output
42
+ - `<noun>-<verb>.schema.json` - Compound names
43
+
44
+ ### Adding a New Schema
45
+
46
+ 1. Create `spec/output-schemas/<name>.schema.json`
47
+ 2. Add contract test in `test/spec/schemas/`
48
+ 3. Reference in spec document
49
+
50
+ ## Contract Tests
51
+
52
+ Tests in `test/spec/schemas/` validate outputs against schemas:
53
+
54
+ ```typescript
55
+ import schema from "../../spec/output-schemas/search-results.schema.json";
56
+
57
+ test("search --json matches schema", async () => {
58
+ const result = await runSearch("query", { json: true });
59
+ expect(() => validate(schema, result)).not.toThrow();
60
+ });
61
+ ```
62
+
63
+ ## Spec Documents
64
+
65
+ ### cli.md
66
+
67
+ - Exit codes and meanings
68
+ - Global flags
69
+ - Output format support matrix
70
+ - All commands with options
71
+
72
+ ### mcp.md
73
+
74
+ - Server capabilities
75
+ - Tool schemas and responses
76
+ - Resource URI schemes
77
+ - Error codes
78
+
79
+ ### evals.md
80
+
81
+ - Evaluation metrics
82
+ - Test case format
83
+ - Scoring methodology
package/spec/CLAUDE.md ADDED
@@ -0,0 +1,83 @@
1
+ # Specifications
2
+
3
+ Interface contracts and schemas for GNO.
4
+
5
+ ## Structure
6
+
7
+ ```
8
+ spec/
9
+ ├── cli.md # CLI commands, flags, exit codes
10
+ ├── mcp.md # MCP tools, resources, schemas
11
+ ├── evals.md # Evaluation framework spec
12
+ ├── db/
13
+ │ └── schema.sql # Database schema
14
+ └── output-schemas/ # JSON schemas for all outputs
15
+ ├── search-results.schema.json
16
+ ├── ask.schema.json
17
+ ├── status.schema.json
18
+ └── ...
19
+ ```
20
+
21
+ ## Spec-First Workflow
22
+
23
+ When adding/modifying commands or outputs:
24
+
25
+ 1. **Update spec first** - Define the interface before implementation
26
+ 2. **Add/update JSON schema** - If output shape changes
27
+ 3. **Add contract tests** - In `test/spec/schemas/`
28
+ 4. **Implement** - Code to match spec
29
+ 5. **Verify** - `bun test` passes
30
+
31
+ ## JSON Schemas
32
+
33
+ Schemas define the structure of all JSON outputs:
34
+
35
+ - Validated by contract tests
36
+ - Used for documentation
37
+ - Enable type generation
38
+
39
+ ### Schema Naming
40
+
41
+ - `<command>.schema.json` - Single command output
42
+ - `<noun>-<verb>.schema.json` - Compound names
43
+
44
+ ### Adding a New Schema
45
+
46
+ 1. Create `spec/output-schemas/<name>.schema.json`
47
+ 2. Add contract test in `test/spec/schemas/`
48
+ 3. Reference in spec document
49
+
50
+ ## Contract Tests
51
+
52
+ Tests in `test/spec/schemas/` validate outputs against schemas:
53
+
54
+ ```typescript
55
+ import schema from "../../spec/output-schemas/search-results.schema.json";
56
+
57
+ test("search --json matches schema", async () => {
58
+ const result = await runSearch("query", { json: true });
59
+ expect(() => validate(schema, result)).not.toThrow();
60
+ });
61
+ ```
62
+
63
+ ## Spec Documents
64
+
65
+ ### cli.md
66
+
67
+ - Exit codes and meanings
68
+ - Global flags
69
+ - Output format support matrix
70
+ - All commands with options
71
+
72
+ ### mcp.md
73
+
74
+ - Server capabilities
75
+ - Tool schemas and responses
76
+ - Resource URI schemes
77
+ - Error codes
78
+
79
+ ### evals.md
80
+
81
+ - Evaluation metrics
82
+ - Test case format
83
+ - Scoring methodology
@@ -0,0 +1,137 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "GNO Bench Fixture",
4
+ "type": "object",
5
+ "required": ["version", "queries"],
6
+ "additionalProperties": false,
7
+ "properties": {
8
+ "version": { "const": 1 },
9
+ "metadata": {
10
+ "type": "object",
11
+ "additionalProperties": false,
12
+ "properties": {
13
+ "name": { "type": "string" },
14
+ "description": { "type": "string" },
15
+ "tags": { "type": "array", "items": { "type": "string" } }
16
+ }
17
+ },
18
+ "collection": { "type": "string", "minLength": 1 },
19
+ "topK": { "type": "integer", "minimum": 1 },
20
+ "candidateLimit": { "type": "integer", "minimum": 1 },
21
+ "modes": {
22
+ "type": "array",
23
+ "items": {
24
+ "oneOf": [
25
+ {
26
+ "type": "string",
27
+ "enum": [
28
+ "bm25",
29
+ "vector",
30
+ "hybrid",
31
+ "fast",
32
+ "no-rerank",
33
+ "thorough"
34
+ ]
35
+ },
36
+ {
37
+ "type": "object",
38
+ "additionalProperties": false,
39
+ "properties": {
40
+ "name": { "type": "string", "minLength": 1 },
41
+ "type": {
42
+ "type": "string",
43
+ "enum": ["bm25", "vector", "hybrid"]
44
+ },
45
+ "mode": {
46
+ "type": "string",
47
+ "enum": [
48
+ "bm25",
49
+ "vector",
50
+ "hybrid",
51
+ "fast",
52
+ "no-rerank",
53
+ "thorough"
54
+ ]
55
+ },
56
+ "noExpand": { "type": "boolean" },
57
+ "noRerank": { "type": "boolean" },
58
+ "candidateLimit": { "type": "integer", "minimum": 1 },
59
+ "limit": { "type": "integer", "minimum": 1 },
60
+ "queryModes": {
61
+ "type": "array",
62
+ "items": { "$ref": "#/definitions/queryMode" }
63
+ }
64
+ }
65
+ }
66
+ ]
67
+ }
68
+ },
69
+ "queries": {
70
+ "type": "array",
71
+ "minItems": 1,
72
+ "items": {
73
+ "type": "object",
74
+ "required": ["id", "query"],
75
+ "additionalProperties": false,
76
+ "properties": {
77
+ "id": { "type": "string", "minLength": 1 },
78
+ "query": { "type": "string", "minLength": 1 },
79
+ "expected": {
80
+ "type": "array",
81
+ "items": { "type": "string", "minLength": 1 }
82
+ },
83
+ "expectedDocuments": {
84
+ "type": "array",
85
+ "items": { "type": "string", "minLength": 1 }
86
+ },
87
+ "expectedUris": {
88
+ "type": "array",
89
+ "items": { "type": "string", "minLength": 1 }
90
+ },
91
+ "judgments": {
92
+ "type": "array",
93
+ "items": {
94
+ "type": "object",
95
+ "required": ["relevance"],
96
+ "additionalProperties": false,
97
+ "properties": {
98
+ "docid": { "type": "string", "minLength": 1 },
99
+ "doc": { "type": "string", "minLength": 1 },
100
+ "uri": { "type": "string", "minLength": 1 },
101
+ "relevance": { "type": "number", "minimum": 0 }
102
+ },
103
+ "anyOf": [
104
+ { "required": ["docid"] },
105
+ { "required": ["doc"] },
106
+ { "required": ["uri"] }
107
+ ]
108
+ }
109
+ },
110
+ "collection": { "type": "string", "minLength": 1 },
111
+ "topK": { "type": "integer", "minimum": 1 },
112
+ "queryModes": {
113
+ "type": "array",
114
+ "items": { "$ref": "#/definitions/queryMode" }
115
+ }
116
+ },
117
+ "anyOf": [
118
+ { "required": ["expected"] },
119
+ { "required": ["expectedDocuments"] },
120
+ { "required": ["expectedUris"] },
121
+ { "required": ["judgments"] }
122
+ ]
123
+ }
124
+ }
125
+ },
126
+ "definitions": {
127
+ "queryMode": {
128
+ "type": "object",
129
+ "required": ["mode", "text"],
130
+ "additionalProperties": false,
131
+ "properties": {
132
+ "mode": { "type": "string", "enum": ["term", "intent", "hyde"] },
133
+ "text": { "type": "string", "minLength": 1 }
134
+ }
135
+ }
136
+ }
137
+ }