@gmickel/gno 1.22.0 → 1.24.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 (59) hide show
  1. package/README.md +33 -12
  2. package/assets/skill/SKILL.md +41 -19
  3. package/package.json +1 -1
  4. package/spec/cli.md +127 -20
  5. package/spec/evals-agentic.md +35 -0
  6. package/spec/evals.md +6 -0
  7. package/spec/mcp.md +18 -0
  8. package/spec/output-schemas/query-diagnose-v1.schema.json +123 -0
  9. package/spec/output-schemas/query-diagnose.schema.json +89 -2
  10. package/spec/output-schemas/setup-activation-result.schema.json +456 -0
  11. package/spec/output-schemas/setup-command-result.schema.json +93 -0
  12. package/spec/output-schemas/setup-receipt.schema.json +258 -0
  13. package/spec/output-schemas/setup-semantic-receipt.schema.json +195 -0
  14. package/src/app/context-runtime-types.ts +3 -0
  15. package/src/app/context-runtime.ts +1 -0
  16. package/src/app/context-surface.ts +4 -2
  17. package/src/cli/commands/ask.ts +31 -20
  18. package/src/cli/commands/completion/scripts.ts +2 -0
  19. package/src/cli/commands/context-build.ts +17 -7
  20. package/src/cli/commands/embed.ts +7 -2
  21. package/src/cli/commands/query.ts +58 -37
  22. package/src/cli/commands/search.ts +29 -19
  23. package/src/cli/commands/setup-activation.ts +324 -0
  24. package/src/cli/commands/setup-semantic.ts +591 -0
  25. package/src/cli/commands/setup.ts +410 -0
  26. package/src/cli/commands/vsearch.ts +31 -22
  27. package/src/cli/options.ts +39 -0
  28. package/src/cli/program.ts +112 -0
  29. package/src/cli/setup-semantic-worker.ts +177 -0
  30. package/src/config/defaults.ts +10 -1
  31. package/src/config/types.ts +71 -0
  32. package/src/core/config-mutation.ts +94 -64
  33. package/src/core/file-lock.ts +70 -31
  34. package/src/core/folder-setup-planning.ts +453 -0
  35. package/src/core/folder-setup.ts +490 -0
  36. package/src/core/project-affinity-surface.ts +114 -0
  37. package/src/core/project-affinity.ts +330 -0
  38. package/src/core/setup-activation.ts +309 -0
  39. package/src/core/setup-receipt.ts +321 -0
  40. package/src/core/validation.ts +20 -1
  41. package/src/mcp/tools/ask.ts +10 -1
  42. package/src/mcp/tools/context.ts +18 -0
  43. package/src/mcp/tools/index.ts +13 -2
  44. package/src/mcp/tools/query.ts +12 -0
  45. package/src/mcp/tools/search.ts +7 -0
  46. package/src/mcp/tools/vsearch.ts +7 -0
  47. package/src/pipeline/diagnose.ts +48 -3
  48. package/src/pipeline/explain.ts +54 -13
  49. package/src/pipeline/hybrid.ts +100 -59
  50. package/src/pipeline/project-affinity.ts +162 -0
  51. package/src/pipeline/search.ts +76 -10
  52. package/src/pipeline/types.ts +9 -0
  53. package/src/pipeline/vsearch.ts +117 -91
  54. package/src/sdk/client.ts +80 -20
  55. package/src/sdk/index.ts +2 -0
  56. package/src/sdk/types.ts +20 -7
  57. package/src/serve/connectors.ts +29 -2
  58. package/src/serve/context-capsule.ts +18 -1
  59. package/src/serve/routes/api.ts +69 -0
package/README.md CHANGED
@@ -17,6 +17,17 @@
17
17
 
18
18
  GNO is a local knowledge engine for notes, code, PDFs, Office docs, meeting transcripts, and reference material. It gives you fast keyword search, semantic retrieval, grounded answers with citations, wiki-style linking, and a real workspace UI, while keeping the whole stack local by default.
19
19
 
20
+ CLI retrieval also uses the current repository/workspace as a transparent soft
21
+ ranking signal. A trusted local cwd or repeatable `--project-root` can add at
22
+ most `+0.03` to matching collection results; `--no-project-affinity` disables
23
+ it, and explicit roots replace cwd inference. It never overrides collection,
24
+ tag, date, exclude, or egress filters. SDK, REST, and MCP `projectHints` are
25
+ opaque, untrusted, limited to 16, and intentionally have zero ranking effect:
26
+ those surfaces never probe caller or server filesystem paths. Trusted local
27
+ diagnose output uses closed `schemaVersion: "1.1"` redacted affinity metadata;
28
+ absent, disabled, and remote/untrusted diagnose requests preserve exact legacy
29
+ v1.0 bytes and omit `affinity`.
30
+
20
31
  Use it when:
21
32
 
22
33
  - your notes live in more than one folder
@@ -39,8 +50,10 @@ Use it when:
39
50
  # Install
40
51
  bun install -g @gmickel/gno
41
52
 
42
- # Add a few collections
43
- gno init ~/notes --name notes
53
+ # Prove the first folder immediately; semantic work continues independently
54
+ gno setup ~/notes --name notes
55
+
56
+ # Add more collections with the granular commands
44
57
  gno collection add ~/work/docs --name work-docs --pattern "**/*.{md,pdf,docx}"
45
58
  gno collection add ~/work/gno/src --name gno-code --pattern "**/*.{ts,tsx,js,jsx}"
46
59
 
@@ -49,7 +62,7 @@ gno context add "notes:" "Personal notes, journal entries, and long-form ideas"
49
62
  gno context add "work-docs:" "Architecture docs, runbooks, RFCs, meeting notes"
50
63
  gno context add "gno-code:" "Source code for the GNO application"
51
64
 
52
- # Index + embed
65
+ # Sync the additional collections, then embed when you want semantic retrieval
53
66
  gno update --yes
54
67
  gno embed
55
68
 
@@ -94,12 +107,16 @@ gno daemon --detach # headless continuous indexing (background; --status / --st
94
107
 
95
108
  <!-- public-truth:current-version -->
96
109
 
97
- > Current release: **v1.22.0** — see [CHANGELOG.md](./CHANGELOG.md)
110
+ > Current release: **v1.24.0** — see [CHANGELOG.md](./CHANGELOG.md)
98
111
 
99
112
  <!-- /public-truth -->
100
113
 
101
114
  > Full release history: [CHANGELOG.md](./CHANGELOG.md)
102
115
 
116
+ - **Project-aware retrieval affinity**: trusted local CLI searches can use the
117
+ current workspace or explicit `--project-root` values as a transparent,
118
+ explainable `+0.03` soft ranking signal. Filters remain hard, and untrusted
119
+ SDK, REST, MCP, and Web hints never probe paths or affect ranking.
103
120
  - **Retrieval-proven activation**: `gno status`, `gno doctor`, REST, and the
104
121
  Web/Desktop dashboard now share a per-folder lexical retrieval proof. Local
105
122
  semantic readiness remains independent, and installed MCP targets can run an
@@ -203,8 +220,7 @@ gno query "ECONNREFUSED 127.0.0.1:5432" --thorough
203
220
  ## Quick Start
204
221
 
205
222
  ```bash
206
- gno init ~/notes --name notes # Point at your docs
207
- gno index # Build search index
223
+ gno setup ~/notes --name notes # Build BM25 and prove an exact local result
208
224
  gno daemon --detach # Keep index fresh in the background (macOS/Linux)
209
225
  gno query "auth best practices" # Hybrid search
210
226
  gno ask "summarize the API" --answer # AI answer with citations
@@ -239,14 +255,19 @@ brew install sqlite3
239
255
  Verify the local installation and corpus-derived lexical retrieval:
240
256
 
241
257
  ```bash
242
- gno doctor
243
- gno status --json
258
+ gno setup ~/notes --name notes
244
259
  ```
245
260
 
246
- `gno status` is passive with respect to models and connectors and exits 0 even
247
- when its structured activation state is degraded. `gno doctor` exits 2 when any
248
- configured folder fails the lexical proof; semantic models may still be pending
249
- without blocking BM25 search.
261
+ `gno setup` returns only after BM25 finds an exact `gno://` result from the
262
+ folder. It is safe to rerun: the same canonical folder and collection are
263
+ reused. Semantic indexing is a separate one-shot process; `--no-semantic`
264
+ records an explicit skip. Add repeatable `--connector <id>` flags only when you
265
+ also want supported agent integrations installed and checked. Setup is direct
266
+ and standalone—it never attaches to `serve`, `daemon`, Web, or MCP.
267
+
268
+ Use `gno status --json` for passive state and `gno doctor` for diagnostics.
269
+ Semantic pending and connector follow-up never invalidate proven lexical
270
+ search.
250
271
 
251
272
  <!-- public-truth:supported-platforms -->
252
273
 
@@ -30,12 +30,19 @@ network boundaries.
30
30
  ## Quick Start
31
31
 
32
32
  ```bash
33
- gno init # Initialize in current directory
34
- gno collection add ~/docs --name docs # Add folder to index
35
- gno index # Build index (ingest + embed)
33
+ gno setup ~/docs --name docs # Index + prove exact BM25; semantic continues
36
34
  gno search "your query" # BM25 keyword search
37
35
  ```
38
36
 
37
+ `gno setup` is the default activation path. It is idempotent, returns only
38
+ after exact lexical proof, and runs directly without resident/Web/MCP
39
+ attachment. Use `--no-semantic` to start no worker and record skipped state.
40
+ Use repeatable `--connector` with `claude-code-skill`,
41
+ `claude-desktop-mcp`, `cursor-mcp`, `codex-skill`, `opencode-skill`,
42
+ `openclaw-skill`, or `hermes-skill`. Connector skips/failures can return
43
+ `completed_with_actions` without invalidating lexical success. Skill targets
44
+ are installed but report `target_runtime_unverifiable`.
45
+
39
46
  ## Recipe Router
40
47
 
41
48
  Use these recipe files when the task is more than a one-off lookup. Read only
@@ -63,22 +70,22 @@ Recipe rules:
63
70
 
64
71
  ## Command Overview
65
72
 
66
- | Category | Commands | Description |
67
- | ------------ | ----------------------------------------------------------------------- | ------------------------------------------------------------------------ |
68
- | **Search** | `search`, `vsearch`, `query`, `ask` | Find documents by keywords, meaning, or get AI answers |
69
- | **Links** | `links`, `backlinks`, `similar`, `graph`, `graph query` | Navigate document relationships and typed connections |
70
- | **Retrieve** | `get`, `multi-get`, `ls` | Fetch document content by URI or ID |
71
- | **Index** | `init`, `collection add/list/remove`, `index`, `update`, `embed` | Set up and maintain document index |
72
- | **Tags** | `tags`, `tags add`, `tags rm` | Organize and filter documents |
73
- | **Context** | `context add/list/rm/check/build/verify/watch/watches/reverify/unwatch` | Configure guidance or compile, verify, and watch saved evidence Capsules |
74
- | **Changes** | `changes`, `diff`, `impact` | Inspect bounded metadata history and dependency impact |
75
- | **Traces** | `trace list/show/label/export/replay/delete/purge` | Manage and replay private retrieval receipts |
76
- | **Models** | `models list/use/pull/clear/path` | Manage local AI models |
77
- | **Serve** | `serve`, `daemon` | One resident Web/headless gateway and watcher |
78
- | **Publish** | `publish export` | Export gno.sh publish artifacts |
79
- | **MCP** | `mcp`, `mcp install/uninstall/status` | AI assistant integration |
80
- | **Skill** | `skill install/uninstall/show/paths` | Install skill for AI agents |
81
- | **Admin** | `status`, `doctor`, `cleanup`, `reset`, `vec`, `completion` | Maintenance and diagnostics |
73
+ | Category | Commands | Description |
74
+ | ------------ | ------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
75
+ | **Search** | `search`, `vsearch`, `query`, `ask` | Find documents by keywords, meaning, or get AI answers |
76
+ | **Links** | `links`, `backlinks`, `similar`, `graph`, `graph query` | Navigate document relationships and typed connections |
77
+ | **Retrieve** | `get`, `multi-get`, `ls` | Fetch document content by URI or ID |
78
+ | **Index** | `setup`, `init`, `collection add/list/remove`, `index`, `update`, `embed` | Prove first retrieval, then maintain the document index |
79
+ | **Tags** | `tags`, `tags add`, `tags rm` | Organize and filter documents |
80
+ | **Context** | `context add/list/rm/check/build/verify/watch/watches/reverify/unwatch` | Configure guidance or compile, verify, and watch saved evidence Capsules |
81
+ | **Changes** | `changes`, `diff`, `impact` | Inspect bounded metadata history and dependency impact |
82
+ | **Traces** | `trace list/show/label/export/replay/delete/purge` | Manage and replay private retrieval receipts |
83
+ | **Models** | `models list/use/pull/clear/path` | Manage local AI models |
84
+ | **Serve** | `serve`, `daemon` | One resident Web/headless gateway and watcher |
85
+ | **Publish** | `publish export` | Export gno.sh publish artifacts |
86
+ | **MCP** | `mcp`, `mcp install/uninstall/status` | AI assistant integration |
87
+ | **Skill** | `skill install/uninstall/show/paths` | Install skill for AI agents |
88
+ | **Admin** | `status`, `doctor`, `cleanup`, `reset`, `vec`, `completion` | Maintenance and diagnostics |
82
89
 
83
90
  ## Search Modes
84
91
 
@@ -108,8 +115,23 @@ Recipe rules:
108
115
  --json JSON output
109
116
  --files URI list output
110
117
  --line-numbers Include line numbers
118
+ --project-root <path> Trusted local root; repeatable and replaces cwd affinity
119
+ --no-project-affinity Disable trusted local project-aware ranking
111
120
  ```
112
121
 
122
+ CLI searches use the current repository/worktree as a soft signal by default.
123
+ A matching collection can receive at most `+0.03`; roots never stack, all
124
+ auxiliary signals share `±0.08`, and collection/tag/date/exclude/egress filters
125
+ stay hard. Use `--project-root` for explicit trusted roots or
126
+ `--no-project-affinity` to disable it.
127
+
128
+ Do not treat MCP/SDK/REST `projectHints` as paths. They are opaque, untrusted,
129
+ limited to 16, never trigger filesystem probing, and currently produce zero
130
+ affinity. Explain uses redacted aliases only. Diagnose preserves exact closed
131
+ v1.0 bytes and omits `affinity` for absent, disabled, and remote/untrusted
132
+ inputs; trusted local diagnose uses closed v1.1 redacted metadata, including an
133
+ explicit unmatched state. The Web UI does not infer a browser project root.
134
+
113
135
  ## Advanced: Structured Query Modes (query/ask only)
114
136
 
115
137
  Use `--query-mode` to combine multiple retrieval strategies in one query (repeatable):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gmickel/gno",
3
- "version": "1.22.0",
3
+ "version": "1.24.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",
package/spec/cli.md CHANGED
@@ -64,6 +64,7 @@ equivalent files fail closed as ambiguous.
64
64
  | ------------------ | ------ | ------- | ----- | ---- | ----- | -------- |
65
65
  | status | yes | no | no | yes | no | terminal |
66
66
  | init | no | no | no | no | no | terminal |
67
+ | setup | yes | no | no | no | no | terminal |
67
68
  | collection add | no | no | no | no | no | terminal |
68
69
  | collection list | yes | no | no | yes | no | terminal |
69
70
  | collection remove | no | no | no | no | no | terminal |
@@ -353,6 +354,96 @@ projected wiki/markdown edges and surface in graph traversal/diagnose metadata.
353
354
 
354
355
  ---
355
356
 
357
+ ### gno setup
358
+
359
+ Add or reuse one folder collection, build its lexical index, and prove a real
360
+ corpus-derived retrieval before reporting success. Semantic indexing is handed
361
+ to one standalone background worker and never delays lexical success.
362
+
363
+ **Synopsis:**
364
+
365
+ ```bash
366
+ gno setup <folder> [-n|--name <name>] [--exclude <pattern>]...
367
+ [--authorize-secret-risk] [--connector <id>]...
368
+ [--no-semantic] [--json]
369
+ ```
370
+
371
+ **Options:**
372
+
373
+ | Option | Type | Default | Description |
374
+ | ------------------------- | ---------- | ------------- | ---------------------------------------------------------------------------- |
375
+ | `-n, --name <name>` | string | dirname | Requested collection name; exact-root reruns reuse the configured collection |
376
+ | `--exclude <pattern>` | repeatable | core defaults | One literal exclusion per occurrence; never CSV |
377
+ | `--authorize-secret-risk` | boolean | false | Explicitly authorize likely credentials, private keys, or env files |
378
+ | `--connector <id>` | repeatable | none | Install or reuse and verify one supported connector after lexical proof |
379
+ | `--no-semantic` | boolean | false | Prove lexical retrieval but record semantic work as skipped |
380
+ | `--json` | boolean | false | Emit one closed setup result object |
381
+
382
+ Omitting `--exclude` preserves the core create defaults or the filters already
383
+ configured for an exact-root rerun. An empty occurrence is invalid. Global
384
+ `--yes` accepts safe defaults only; it never authorizes secret risk. Only an
385
+ interactive terminal may ask one default-No question after the lexical core
386
+ returns `secret_risk`. JSON, `--yes`, non-TTY, decline, and EOF fail closed.
387
+
388
+ The command bootstraps missing config/data/database state without adding the
389
+ folder through `init`, then runs the folder setup transaction. Success requires
390
+ a completed `FolderSetupReceipt@1.0`, `activation.ready=true`, and a non-empty
391
+ exact `activation.evidence.resultUri`. Terminal stage progress uses stderr;
392
+ `--quiet` suppresses progress but not the final result. JSON writes exactly one
393
+ canonical result to stdout on both success and domain failure, with no progress.
394
+
395
+ After lexical proof, the command records one private atomic
396
+ `setup-semantic@1.0` receipt per canonical index/folder and starts one detached,
397
+ collection-scoped Bun worker. A matching live worker is reused; a dead worker is
398
+ replaced; and a live worker with an older identity remains authoritative until
399
+ it exits so its completion receipt cannot be stranded. A later setup rerun may
400
+ then schedule the new identity. The worker uses the normal model
401
+ download/offline policy, records `completed` only when embedding and vector
402
+ synchronization finish without errors, and exits. Spawn, download, partial
403
+ embedding, and vector-sync failures retain an exact foreground
404
+ `gno ... embed <collection>` remediation and never change proven lexical exit 0.
405
+ Direct setup never contacts a resident, MCP, or Web runtime.
406
+
407
+ `--connector` is explicit and repeatable; omission performs no connector
408
+ inspection, installation, or verification. Supported IDs are
409
+ `claude-code-skill`, `claude-desktop-mcp`, `cursor-mcp`, `codex-skill`,
410
+ `opencode-skill`, `openclaw-skill`, and `hermes-skill`. Exact duplicates dedupe
411
+ in first-seen order. Unknown IDs fail before setup side effects.
412
+ Any connector-mode JSON invocation emits `setup-activation-result@1.0`.
413
+ Argument or lexical failure uses outer `status: failed`, nests the unchanged
414
+ failed setup result, and keeps `connectors: []`; it retains the original setup
415
+ exit code and performs no connector action.
416
+
417
+ After proven lexical success and after the lexical store closes, the direct CLI
418
+ opens a new standalone store for connector composition. Missing targets use the
419
+ existing read-only installer; existing entries are reused without overwrite.
420
+ Malformed or unreadable entries are preserved. MCP targets run the shipped
421
+ bounded read-only activation smoke. Skill targets install but return
422
+ `skipped/target_runtime_unverifiable` because they expose no safe runtime hook.
423
+ Connector failures or skips do not roll back lexical success: the command exits
424
+ 0 with `completed_with_actions` and bounded per-target remediation. No raw child
425
+ output or client config path is serialized. Reruns delegate passed-receipt reuse
426
+ and recoverable retry to the shipped activation verifier; setup introduces no
427
+ second connector fingerprint or cache.
428
+
429
+ **Structured schemas:**
430
+
431
+ - [`setup-command-result@1.0`](./output-schemas/setup-command-result.schema.json)
432
+ - [`setup-activation-result@1.0`](./output-schemas/setup-activation-result.schema.json)
433
+ - [`setup-semantic@1.0`](./output-schemas/setup-semantic-receipt.schema.json)
434
+ - [`FolderSetupReceipt@1.0`](./output-schemas/setup-receipt.schema.json)
435
+
436
+ **Exit Codes:**
437
+
438
+ - 0: Lexical setup completed with a real exact result URI; semantic state may
439
+ be scheduled, running, pending, completed, or skipped; requested connector
440
+ actions may require bounded follow-up
441
+ - 1: Invalid/safe-input rejection, collection/filter/index disagreement,
442
+ secret-risk refusal, or declined confirmation
443
+ - 2: Config, receipt, IO, store, indexing, proof, or internal invariant failure
444
+
445
+ ---
446
+
356
447
  ### gno collection add
357
448
 
358
449
  Add a new collection to the index.
@@ -749,22 +840,24 @@ gno search <query> [-n <num>] [--min-score <num>] [-c <collection>] [--since <da
749
840
 
750
841
  **Options:**
751
842
 
752
- | Option | Type | Default | Description |
753
- | ------------------ | ------- | ------------------------- | --------------------------------------------------------------------------------------------- |
754
- | `-n` | integer | 5 (20 for --json/--files) | Max results |
755
- | `--min-score` | number | 0 | Minimum score threshold |
756
- | `-c, --collection` | string | all | Filter to collection |
757
- | `--since` | string | none | Modified-at lower bound (ISO date/time or relative token) |
758
- | `--until` | string | none | Modified-at upper bound (ISO date/time or relative token) |
759
- | `--category` | string | none | Filter to docs with matching category/content type (comma-separated) |
760
- | `--author` | string | none | Filter to docs where author contains value (case-insensitive) |
761
- | `--intent` | string | none | Disambiguating context for ambiguous queries; steers snippets without being searched directly |
762
- | `--exclude` | string | none | Hard-prune docs containing any comma-separated term in title/path/body |
763
- | `--tags-all` | string | none | Filter to docs with ALL tags (comma-separated) |
764
- | `--tags-any` | string | none | Filter to docs with ANY tag (comma-separated) |
765
- | `--full` | boolean | false | Include full mirror content instead of snippet |
766
- | `--line-numbers` | boolean | false | Include line numbers in output |
767
- | `--lang` | string | auto | Language filter/hint (BCP-47) |
843
+ | Option | Type | Default | Description |
844
+ | ----------------------- | -------- | ------------------------- | --------------------------------------------------------------------------------------------- |
845
+ | `-n` | integer | 5 (20 for --json/--files) | Max results |
846
+ | `--min-score` | number | 0 | Minimum score threshold |
847
+ | `-c, --collection` | string | all | Filter to collection |
848
+ | `--since` | string | none | Modified-at lower bound (ISO date/time or relative token) |
849
+ | `--until` | string | none | Modified-at upper bound (ISO date/time or relative token) |
850
+ | `--category` | string | none | Filter to docs with matching category/content type (comma-separated) |
851
+ | `--author` | string | none | Filter to docs where author contains value (case-insensitive) |
852
+ | `--intent` | string | none | Disambiguating context for ambiguous queries; steers snippets without being searched directly |
853
+ | `--exclude` | string | none | Hard-prune docs containing any comma-separated term in title/path/body |
854
+ | `--tags-all` | string | none | Filter to docs with ALL tags (comma-separated) |
855
+ | `--tags-any` | string | none | Filter to docs with ANY tag (comma-separated) |
856
+ | `--project-root` | string[] | cwd | Trusted project root; repeatable, replaces default cwd/repository affinity |
857
+ | `--no-project-affinity` | boolean | false | Disable project-aware soft ranking; invalid with `--project-root` |
858
+ | `--full` | boolean | false | Include full mirror content instead of snippet |
859
+ | `--line-numbers` | boolean | false | Include line numbers in output |
860
+ | `--lang` | string | auto | Language filter/hint (BCP-47) |
768
861
 
769
862
  **Scoring:**
770
863
 
@@ -824,7 +917,8 @@ Vector semantic search over indexed documents.
824
917
  gno vsearch <query> [-n <num>] [--min-score <num>] [-c <collection>] [--since <date>] [--until <date>] [--category <values>] [--author <text>] [--intent <text>] [--exclude <values>] [--tags-all <tags>] [--tags-any <tags>] [--full] [--line-numbers] [--lang <bcp47>] [--json|--files|--csv|--md|--xml]
825
918
  ```
826
919
 
827
- **Options:** Same as `gno search` (including temporal/category/author and tag filters)
920
+ **Options:** Same as `gno search` (including temporal/category/author, tag, and
921
+ project-affinity controls).
828
922
 
829
923
  **Scoring:**
830
924
 
@@ -870,6 +964,9 @@ gno query diagnose <query> --target <doc> [-n <num>] [--min-score <num>] [-c <co
870
964
  | `--explain` | boolean | Print retrieval explanation to stderr |
871
965
  | `--target` | ref | Required for `query diagnose`; target document to diagnose |
872
966
 
967
+ `query diagnose` accepts the same `--project-root` and
968
+ `--no-project-affinity` controls as `query`.
969
+
873
970
  **Compatibility / Migration:**
874
971
 
875
972
  - Legacy query invocations remain valid (`gno query "<text>"`, `--fast`, `--thorough`, `--no-expand`, `--no-rerank`).
@@ -882,8 +979,12 @@ gno query diagnose <query> --target <doc> [-n <num>] [--min-score <num>] [-c <co
882
979
  **Diagnose Output:**
883
980
 
884
981
  `gno query diagnose` wraps the shared `diagnoseQueryTarget()` core and emits
885
- `query-diagnose.schema.json` for `--json`. The payload requires
886
- `schemaVersion: "1.0"`, resolves the target first, reports `target.status`
982
+ `query-diagnose.schema.json` for `--json`. No trusted affinity input preserves
983
+ the exact closed `schemaVersion: "1.0"` payload and omits `affinity`; the legacy
984
+ contract remains in `query-diagnose-v1.schema.json`. A resolved trusted CLI cwd
985
+ or explicit project root emits `schemaVersion: "1.1"` and requires closed,
986
+ redacted `affinity` metadata, including unmatched state. The payload resolves
987
+ the target first, reports `target.status`
887
988
  (`not_found|inactive|no_indexed_content|filtered_out|diagnosed`), and only runs
888
989
  stage tracing for `diagnosed` targets. Stages report
889
990
  `present`, `rank`, `score`, `survived`, `dropReason`, `status`, and
@@ -992,6 +1093,8 @@ gno ask <query> [-n <num>] [-c <collection>] [--lang <bcp47>] [--since <date>] [
992
1093
  | `--no-expand` | boolean | false | Disable query expansion |
993
1094
  | `--no-rerank` | boolean | false | Disable cross-encoder reranking |
994
1095
  | `--show-sources` | boolean | false | Show all retrieved sources (not just cited) |
1096
+ | `--project-root` | string[] | cwd | Trusted project root; repeatable, replaces default cwd/repository affinity |
1097
+ | `--no-project-affinity` | boolean | false | Disable project-aware soft ranking; invalid with `--project-root` |
995
1098
 
996
1099
  **Output (JSON):**
997
1100
  See [Output Schemas](./output-schemas/ask.schema.json)
@@ -1315,7 +1418,7 @@ written to stderr.
1315
1418
  **Synopsis:**
1316
1419
 
1317
1420
  ```bash
1318
- gno context build "<goal>" --budget <tokens> [--collection <name>] [--fast|--thorough] [--json|--md] [--output <file>]
1421
+ gno context build "<goal>" --budget <tokens> [--collection <name>] [--project-root <path>]... [--no-project-affinity] [--fast|--thorough] [--json|--md] [--output <file>]
1319
1422
  ```
1320
1423
 
1321
1424
  `--budget` is the global token ceiling. `--bytes` optionally sets a separate
@@ -1328,6 +1431,10 @@ repeatable. Tag filters are NFC-normalized, lowercased, deduplicated, and
1328
1431
  validated before retrieval. Result and candidate limits are global across
1329
1432
  repeated collections: the merged result pool is capped once, while candidate
1330
1433
  work is distributed deterministically in canonical collection order.
1434
+ Project affinity defaults to the trusted process cwd/repository. Repeatable
1435
+ `--project-root` values replace that default, are normalized/deduplicated, and
1436
+ are capped at 16. `--no-project-affinity` disables the soft signal and cannot
1437
+ be combined with explicit roots.
1331
1438
 
1332
1439
  JSON is the canonical V1 payload. Markdown is a readable projection of that
1333
1440
  same payload and hard-delimits each untrusted evidence passage. Passage,
@@ -22,6 +22,10 @@ evals/agentic/
22
22
  fixture-db.ts
23
23
  scoring.ts
24
24
  promotion.ts
25
+ project-affinity-contract.ts
26
+ project-affinity-outcome.ts
27
+ project-affinity-promotion.ts
28
+ project-affinity-runtime.ts
25
29
  verified-ask-outcome.ts
26
30
  verified-ask-promotion.ts
27
31
  demos/context-capsule.ts
@@ -68,6 +72,37 @@ evals/fixtures/agentic-retrieval/
68
72
  context-capsule.md
69
73
  ```
70
74
 
75
+ ## Separate project-affinity promotion
76
+
77
+ `project-affinity-cases.json` defines two controlled vector-distance pairs over
78
+ the existing `t456ef70` (`c015`/`c115`) and `t567f081`
79
+ (`c016`/`c116`) task/corpus/oracle identities. The separate closed
80
+ `project-affinity-promotion@1.0` artifact hash-binds those manifest identities;
81
+ it does not add tasks to the authoritative 24-task, 144-receipt matrix or
82
+ change `BenchmarkReport@1`.
83
+
84
+ The target collection starts `0.02` behind, then receives one trusted local
85
+ `+0.03` contribution. Promotion requires correct top-1 to strictly improve to
86
+ `2/2`, exact required evidence to remain retained, zero URI-rank/required
87
+ evidence-coverage loss across all 24 hard-collection tasks, and zero loss for
88
+ `t012ab3c`, `t123bc4d`, `te8f901a`, and `tf901a2b`. It also gates hard-filter
89
+ isolation, absent/disabled/unavailable/untrusted exact zero lanes, shared
90
+ auxiliary cap receipts, and structural store-call/candidate bounds. Structural
91
+ receipts record the complete closed StorePort method map, reject unexpected
92
+ methods, enforce per-method maxima, require candidate requests and returns to
93
+ stay within `3×` the output limit, and require returned candidates not to exceed
94
+ requested candidates. Latency is not a gate.
95
+
96
+ The committed artifacts are
97
+ `baseline/fixture-agent/project-affinity-promotion.json` and `.md`. They contain
98
+ only GNO evidence URIs, hashes, scores, raw filter/regression/zero/auxiliary/
99
+ structural receipts, implementation provenance, and redacted aliases—never
100
+ temporary roots, raw project hints, or absolute paths. An independent validator
101
+ rebinds fixture identities, recomputes summaries/gates/fingerprint from those
102
+ receipts, and compares the committed artifact with a fresh deterministic
103
+ production run. The controlled synthetic lane isolates the score seam and makes
104
+ no general workload superiority claim.
105
+
71
106
  The first fixture version contains 24 original synthetic tasks and 34 Markdown
72
107
  documents under the MIT license. It covers exact identifiers, ambiguity,
73
108
  multi-document comparisons, meeting decisions, temporal questions, typed
package/spec/evals.md CHANGED
@@ -27,6 +27,12 @@ Agent-level evidence sufficiency, exact citation coverage, stopping behavior,
27
27
  and Context Capsule promotion use the separate deterministic
28
28
  [Agentic Retrieval Evaluation Contract](evals-agentic.md).
29
29
 
30
+ That contract also owns a separate closed project-affinity promotion artifact.
31
+ It reuses the immutable 24-task fixture identities while leaving the main task
32
+ inventory and report schema unchanged. The gate records measured top-1,
33
+ evidence, multilingual, hard-filter, zero-lane, score-cap, and structural-call
34
+ outcomes; it does not use a wall-clock threshold.
35
+
30
36
  ## Dependencies
31
37
 
32
38
  ```json
package/spec/mcp.md CHANGED
@@ -218,6 +218,10 @@ Optional fields are `collection`, `limit` (default 5), `minScore`, `lang`,
218
218
  `since`, `until`, `categories`, `author`, `graph`, `noGraph`, `noRerank`,
219
219
  `maxAnswerTokens`, `contextBudgetTokens`, and `contextBudgetBytes`. Input
220
220
  objects are closed.
221
+ `projectHints` is an optional array of at most 16 non-empty caller hints. Hints
222
+ are normalized and deduplicated as opaque values, never resolved against or
223
+ reflected from the MCP server filesystem, and therefore have zero ranking
224
+ effect on the remote channel.
221
225
 
222
226
  `structuredContent` uses the
223
227
  [`ask`](./output-schemas/ask.schema.json) contract. Its `verification` object
@@ -273,6 +277,9 @@ validated before retrieval. `limit` and `candidateLimit` are global across all
273
277
  requested collections: result admission is capped after merging, and
274
278
  rerank/graph candidate work is distributed deterministically in canonical
275
279
  collection order.
280
+ `projectHints` is also accepted as an optional array of at most 16 opaque
281
+ caller hints. It follows the same remote zero-affinity, non-probing, and
282
+ non-reflection contract as all MCP retrieval tools.
276
283
 
277
284
  `structuredContent` is the complete canonical Context Capsule object for
278
285
  application clients. Model-visible text is always one deterministic
@@ -338,6 +345,13 @@ evidence reads. `structuredContent` is the canonical verification receipt.
338
345
 
339
346
  BM25 keyword search over indexed documents.
340
347
 
348
+ All retrieval input schemas (`gno_search`, `gno_vsearch`, `gno_query`, and
349
+ `gno_query_diagnose`) additionally accept optional `projectHints: string[]`
350
+ (maximum 16). Values are trimmed, NFC-normalized, deduplicated, and treated as
351
+ opaque remote hints. The server never stats, realpaths, discovers repositories,
352
+ or infers its cwd from them; remote hints produce redacted zero-affinity
353
+ metadata and no ranking change.
354
+
341
355
  **Input Schema:**
342
356
 
343
357
  ```json
@@ -745,6 +759,10 @@ Structured content includes `schemaVersion`, normalized `query`, `target`
745
759
  metadata/status (`not_found`, `inactive`, `no_indexed_content`,
746
760
  `filtered_out`, or `diagnosed`), `stages` for BM25/vector/fusion/graph/rerank,
747
761
  the selected target `chunk`, and retrieval `meta`.
762
+ MCP inputs are remote and untrusted, so this tool preserves exact v1.0 bytes
763
+ and omits `affinity`, even when `projectHints` are supplied. The shared current
764
+ validation schema is `gno://schemas/query-diagnose@1.1`; its affinity-bearing
765
+ v1.1 branch is reserved for trusted local CLI diagnose requests.
748
766
 
749
767
  Use when an expected target is missing from `gno_query`, when filters may have
750
768
  excluded it, or when an agent needs evidence before raising `candidateLimit`,
@@ -0,0 +1,123 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "gno://schemas/query-diagnose@1.0",
4
+ "title": "GNO Query Diagnose",
5
+ "type": "object",
6
+ "required": ["schemaVersion", "query", "target", "stages", "chunk", "meta"],
7
+ "properties": {
8
+ "schemaVersion": { "type": "string", "const": "1.0" },
9
+ "query": { "type": "string" },
10
+ "target": {
11
+ "type": "object",
12
+ "required": [
13
+ "ref",
14
+ "status",
15
+ "docid",
16
+ "uri",
17
+ "title",
18
+ "contentType",
19
+ "contentTypeSource",
20
+ "categories",
21
+ "graphHints",
22
+ "contentTypeRulesFingerprint",
23
+ "contentTypeFingerprintMatches",
24
+ "mirrorHash",
25
+ "chunkCount",
26
+ "filterReasons"
27
+ ],
28
+ "properties": {
29
+ "ref": { "type": "string" },
30
+ "status": {
31
+ "type": "string",
32
+ "enum": [
33
+ "not_found",
34
+ "inactive",
35
+ "no_indexed_content",
36
+ "filtered_out",
37
+ "diagnosed"
38
+ ]
39
+ },
40
+ "docid": { "type": ["string", "null"], "pattern": "^#[a-f0-9]{6,}$" },
41
+ "uri": { "type": ["string", "null"], "format": "uri" },
42
+ "title": { "type": ["string", "null"] },
43
+ "contentType": { "type": ["string", "null"] },
44
+ "contentTypeSource": { "type": ["string", "null"] },
45
+ "categories": { "type": "array", "items": { "type": "string" } },
46
+ "graphHints": { "type": "array", "items": { "type": "string" } },
47
+ "contentTypeRulesFingerprint": { "type": ["string", "null"] },
48
+ "contentTypeFingerprintMatches": { "type": ["boolean", "null"] },
49
+ "mirrorHash": { "type": ["string", "null"] },
50
+ "chunkCount": { "type": "integer", "minimum": 0 },
51
+ "filterReasons": { "type": "array", "items": { "type": "string" } }
52
+ },
53
+ "additionalProperties": false
54
+ },
55
+ "stages": {
56
+ "type": "array",
57
+ "items": {
58
+ "type": "object",
59
+ "required": [
60
+ "id",
61
+ "status",
62
+ "sourceCount",
63
+ "present",
64
+ "rank",
65
+ "score",
66
+ "survived",
67
+ "dropReason"
68
+ ],
69
+ "properties": {
70
+ "id": {
71
+ "type": "string",
72
+ "enum": ["bm25", "vector", "fusion", "graph", "rerank"]
73
+ },
74
+ "status": { "type": "string", "enum": ["active", "skipped"] },
75
+ "sourceCount": { "type": "integer", "minimum": 0 },
76
+ "present": { "type": "boolean" },
77
+ "rank": { "type": ["integer", "null"], "minimum": 1 },
78
+ "score": { "type": ["number", "null"] },
79
+ "survived": { "type": "boolean" },
80
+ "dropReason": {
81
+ "type": ["string", "null"],
82
+ "enum": ["not_in_candidate_set", "below_cutoff", "skipped", null]
83
+ },
84
+ "reason": { "type": "string" }
85
+ },
86
+ "additionalProperties": false
87
+ }
88
+ },
89
+ "chunk": {
90
+ "type": "object",
91
+ "required": ["seq", "startLine", "endLine", "language"],
92
+ "properties": {
93
+ "seq": { "type": ["integer", "null"], "minimum": 0 },
94
+ "startLine": { "type": ["integer", "null"], "minimum": 1 },
95
+ "endLine": { "type": ["integer", "null"], "minimum": 1 },
96
+ "language": { "type": ["string", "null"] }
97
+ },
98
+ "additionalProperties": false
99
+ },
100
+ "meta": {
101
+ "type": "object",
102
+ "required": ["mode", "vectorsUsed", "reranked", "totalResults"],
103
+ "properties": {
104
+ "mode": { "type": "string", "enum": ["bm25_only", "hybrid"] },
105
+ "vectorsUsed": { "type": "boolean" },
106
+ "reranked": { "type": "boolean" },
107
+ "totalResults": { "type": "integer", "minimum": 0 },
108
+ "queryModes": {
109
+ "type": "object",
110
+ "required": ["term", "intent", "hyde"],
111
+ "properties": {
112
+ "term": { "type": "integer", "minimum": 0 },
113
+ "intent": { "type": "integer", "minimum": 0 },
114
+ "hyde": { "type": "boolean" }
115
+ },
116
+ "additionalProperties": false
117
+ }
118
+ },
119
+ "additionalProperties": false
120
+ }
121
+ },
122
+ "additionalProperties": false
123
+ }