@gmickel/gno 1.25.1 → 1.27.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 (94) hide show
  1. package/README.md +12 -5
  2. package/assets/skill/SKILL.md +37 -17
  3. package/browser-extension/artifacts/{gno-browser-clipper-v1.25.1.zip → gno-browser-clipper-v1.27.0.zip} +0 -0
  4. package/browser-extension/artifacts/gno-browser-clipper-v1.27.0.zip.sha256 +1 -0
  5. package/browser-extension/dist/manifest.json +1 -1
  6. package/package.json +1 -1
  7. package/spec/cli.md +161 -6
  8. package/spec/db/schema.sql +1 -1
  9. package/spec/evals-agentic.md +17 -0
  10. package/spec/mcp.md +25 -6
  11. package/spec/output-schemas/ask.schema.json +3 -0
  12. package/spec/output-schemas/project-profile-apply.schema.json +209 -0
  13. package/spec/output-schemas/project-profile-command.schema.json +160 -0
  14. package/spec/output-schemas/query-diagnose.schema.json +68 -5
  15. package/spec/output-schemas/search-results.schema.json +87 -1
  16. package/spec/output-schemas/setup-profile-result.schema.json +87 -0
  17. package/spec/output-schemas/status.schema.json +24 -0
  18. package/spec/project-profile.schema.json +303 -0
  19. package/src/app/context-runtime-contract.ts +4 -1
  20. package/src/app/context-runtime-types.ts +2 -0
  21. package/src/app/context-runtime.ts +26 -0
  22. package/src/app/verified-ask.ts +6 -1
  23. package/src/cli/commands/ask.ts +8 -1
  24. package/src/cli/commands/collection/add.ts +39 -45
  25. package/src/cli/commands/collection/remove.ts +28 -28
  26. package/src/cli/commands/collection/rename.ts +55 -73
  27. package/src/cli/commands/context/add.ts +37 -26
  28. package/src/cli/commands/context/rm.ts +47 -20
  29. package/src/cli/commands/init.ts +55 -125
  30. package/src/cli/commands/models/use.ts +43 -38
  31. package/src/cli/commands/profile-apply.ts +334 -0
  32. package/src/cli/commands/profile.ts +409 -0
  33. package/src/cli/commands/query.ts +6 -3
  34. package/src/cli/commands/search.ts +6 -1
  35. package/src/cli/commands/setup-activation.ts +205 -54
  36. package/src/cli/commands/setup-profile.ts +223 -0
  37. package/src/cli/commands/setup.ts +3 -0
  38. package/src/cli/commands/status.ts +43 -7
  39. package/src/cli/program.ts +112 -9
  40. package/src/config/content-types.ts +82 -0
  41. package/src/config/index.ts +11 -0
  42. package/src/config/project-profile.ts +374 -0
  43. package/src/config/saver.ts +16 -7
  44. package/src/config/types.ts +53 -2
  45. package/src/core/config-mutation.ts +138 -76
  46. package/src/core/config-write-lock.ts +89 -0
  47. package/src/core/context-compiler.ts +38 -1
  48. package/src/core/context-identity.ts +16 -0
  49. package/src/core/context-resolver.ts +2 -12
  50. package/src/core/folder-setup-planning.ts +6 -21
  51. package/src/core/folder-setup.ts +30 -2
  52. package/src/core/path-rules.ts +53 -0
  53. package/src/core/project-affinity-surface.ts +102 -7
  54. package/src/core/project-profile-apply-state.ts +268 -0
  55. package/src/core/project-profile-apply-validation.ts +95 -0
  56. package/src/core/project-profile-apply.ts +408 -0
  57. package/src/core/project-profile-canonical.ts +71 -0
  58. package/src/core/project-profile-diff.ts +302 -0
  59. package/src/core/project-profile-discovery.ts +519 -0
  60. package/src/core/project-profile-file.ts +37 -0
  61. package/src/core/project-profile-parser.ts +98 -0
  62. package/src/core/project-profile.ts +490 -0
  63. package/src/core/retrieval-replay-candidate.ts +6 -1
  64. package/src/ingestion/sync-options.ts +6 -2
  65. package/src/ingestion/sync.ts +21 -29
  66. package/src/ingestion/types.ts +1 -1
  67. package/src/ingestion/walker.ts +85 -44
  68. package/src/llm/cache.ts +21 -0
  69. package/src/mcp/tools/ask.ts +1 -0
  70. package/src/mcp/tools/index.ts +4 -0
  71. package/src/mcp/tools/query.ts +4 -2
  72. package/src/mcp/tools/search.ts +3 -0
  73. package/src/mcp/tools/status.ts +4 -0
  74. package/src/pipeline/content-type-boost.ts +264 -0
  75. package/src/pipeline/diagnose.ts +46 -19
  76. package/src/pipeline/explain.ts +15 -2
  77. package/src/pipeline/hybrid.ts +170 -74
  78. package/src/pipeline/rerank.ts +45 -15
  79. package/src/pipeline/search.ts +29 -11
  80. package/src/pipeline/types.ts +13 -4
  81. package/src/pipeline/vsearch.ts +30 -10
  82. package/src/sdk/client.ts +19 -3
  83. package/src/sdk/index.ts +1 -0
  84. package/src/sdk/types.ts +21 -5
  85. package/src/serve/config-sync.ts +2 -2
  86. package/src/serve/resident-runtime.ts +1 -0
  87. package/src/serve/routes/api.ts +18 -3
  88. package/src/serve/status-model.ts +2 -0
  89. package/src/serve/status.ts +4 -0
  90. package/src/store/migrations/021-multi-context-identity.ts +37 -0
  91. package/src/store/migrations/index.ts +2 -0
  92. package/src/store/sqlite/adapter.ts +86 -0
  93. package/src/store/types.ts +3 -2
  94. package/browser-extension/artifacts/gno-browser-clipper-v1.25.1.zip.sha256 +0 -1
package/README.md CHANGED
@@ -18,9 +18,10 @@
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
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,
21
+ ranking signal. A trusted explicit `--project-root`, nearest valid
22
+ `.gno/index.yml`, or local cwd can add at most `+0.03` to matching collection
23
+ results, in that precedence order; `--no-project-affinity` disables it. Profile
24
+ defaults stay project-local and never overwrite the user default. It never overrides collection,
24
25
  tag, date, exclude, or egress filters. SDK, REST, and MCP `projectHints` are
25
26
  opaque, untrusted, limited to 16, and intentionally have zero ranking effect:
26
27
  those surfaces never probe caller or server filesystem paths. Trusted local
@@ -53,6 +54,10 @@ bun install -g @gmickel/gno
53
54
  # Prove the first folder immediately; semantic work continues independently
54
55
  gno setup ~/notes --name notes
55
56
 
57
+ # In a repository with .gno/index.yml: preview, apply, and prove its collection
58
+ gno profile diff
59
+ gno setup . --apply-profile
60
+
56
61
  # Add more collections with the granular commands
57
62
  gno collection add ~/work/docs --name work-docs --pattern "**/*.{md,pdf,docx}"
58
63
  gno collection add ~/work/gno/src --name gno-code --pattern "**/*.{ts,tsx,js,jsx}"
@@ -107,7 +112,7 @@ gno daemon --detach # headless continuous indexing (background; --status / --st
107
112
 
108
113
  <!-- public-truth:current-version -->
109
114
 
110
- > Current release: **v1.25.1** — see [CHANGELOG.md](./CHANGELOG.md)
115
+ > Current release: **v1.26.0** — see [CHANGELOG.md](./CHANGELOG.md)
111
116
 
112
117
  <!-- /public-truth -->
113
118
 
@@ -144,7 +149,8 @@ gno daemon --detach # headless continuous indexing (background; --status / --st
144
149
  remote fetch, store listing, or Firefox parity is claimed.
145
150
  - **Schema-lite content types**: optional `contentTypes` rules map configured
146
151
  frontmatter `type` values or path prefixes to canonical `contentType` metadata
147
- in JSON search/query results
152
+ in JSON search/query results and can apply one bounded, explainable
153
+ `searchBoost` without bypassing hard filters
148
154
  - **Publish to [gno.sh](https://gno.sh/publish)**: new `gno publish export` CLI and Web UI action produce a self-contained artifact you upload to the hosted reader — public, secret, invite-only, or locally encrypted before upload
149
155
  - **Retrieval Quality Upgrade**: stronger BM25 lexical handling, code-aware chunking, terminal result hyperlinks, and per-collection model overrides
150
156
  - **Code Embedding Benchmarks**: new benchmark workflow across canonical, real-GNO, and pinned OSS slices for comparing alternate embedding models
@@ -194,6 +200,7 @@ Model guides:
194
200
  - [Code Embeddings](./docs/guides/code-embeddings.md)
195
201
  - [Per-Collection Models](./docs/guides/per-collection-models.md)
196
202
  - [Bring Your Own Models](./docs/guides/bring-your-own-models.md)
203
+ - [Project-Local Retrieval Profiles](./docs/guides/project-profiles.md)
197
204
 
198
205
  ### Fine-Tuned Model Quick Use
199
206
 
@@ -37,6 +37,11 @@ gno search "your query" # BM25 keyword search
37
37
  `gno setup` is the default activation path. It is idempotent, returns only
38
38
  after exact lexical proof, and runs directly without resident/Web/MCP
39
39
  attachment. Use `--no-semantic` to start no worker and record skipped state.
40
+ Inside a repository with `.gno/index.yml`, setup inspects the optional profile
41
+ before mutation. Run `gno profile diff`, then
42
+ `gno setup . --apply-profile` to apply its portable collection/context/content
43
+ rules before setup proves retrieval. Missing/invalid profiles keep ordinary
44
+ setup usable; no profile is applied implicitly.
40
45
  Use repeatable `--connector` with `claude-code-skill`,
41
46
  `claude-desktop-mcp`, `cursor-mcp`, `codex-skill`, `opencode-skill`,
42
47
  `openclaw-skill`, or `hermes-skill`. Connector skips/failures can return
@@ -70,22 +75,22 @@ Recipe rules:
70
75
 
71
76
  ## Command Overview
72
77
 
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 |
78
+ | Category | Commands | Description |
79
+ | ------------ | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
80
+ | **Search** | `search`, `vsearch`, `query`, `ask` | Find documents by keywords, meaning, or get AI answers |
81
+ | **Links** | `links`, `backlinks`, `similar`, `graph`, `graph query` | Navigate document relationships and typed connections |
82
+ | **Retrieve** | `get`, `multi-get`, `ls` | Fetch document content by URI or ID |
83
+ | **Index** | `setup`, `profile check/show/diff/apply`, `init`, `collection add/list/remove`, `index`, `update`, `embed` | Reproduce profile intent, prove retrieval, then maintain the index |
84
+ | **Tags** | `tags`, `tags add`, `tags rm` | Organize and filter documents |
85
+ | **Context** | `context add/list/rm/check/build/verify/watch/watches/reverify/unwatch` | Configure guidance or compile, verify, and watch saved evidence Capsules |
86
+ | **Changes** | `changes`, `diff`, `impact` | Inspect bounded metadata history and dependency impact |
87
+ | **Traces** | `trace list/show/label/export/replay/delete/purge` | Manage and replay private retrieval receipts |
88
+ | **Models** | `models list/use/pull/clear/path` | Manage local AI models |
89
+ | **Serve** | `serve`, `daemon` | One resident Web/headless gateway and watcher |
90
+ | **Publish** | `publish export` | Export gno.sh publish artifacts |
91
+ | **MCP** | `mcp`, `mcp install/uninstall/status` | AI assistant integration |
92
+ | **Skill** | `skill install/uninstall/show/paths` | Install skill for AI agents |
93
+ | **Admin** | `status`, `doctor`, `cleanup`, `reset`, `vec`, `completion` | Maintenance and diagnostics |
89
94
 
90
95
  ## Search Modes
91
96
 
@@ -117,14 +122,29 @@ Recipe rules:
117
122
  --line-numbers Include line numbers
118
123
  --project-root <path> Trusted local root; repeatable and replaces cwd affinity
119
124
  --no-project-affinity Disable trusted local project-aware ranking
125
+ --explain Include retrieval scoring details
120
126
  ```
121
127
 
122
- CLI searches use the current repository/worktree as a soft signal by default.
128
+ CLI searches use explicit `--project-root`, the nearest valid compiled project
129
+ profile, then the current repository/worktree, in that precedence order.
123
130
  A matching collection can receive at most `+0.03`; roots never stack, all
124
131
  auxiliary signals share `±0.08`, and collection/tag/date/exclude/egress filters
125
132
  stay hard. Use `--project-root` for explicit trusted roots or
126
133
  `--no-project-affinity` to disable it.
127
134
 
135
+ Profile affinity defaults are request-local. `gno profile apply` never
136
+ overwrites the user's global `projectAffinity` default, so one repository
137
+ cannot change another repository's fallback. Explain/diagnose identify this
138
+ trusted source as `project_profile`; contexts, content types, source metadata,
139
+ and document fields never become project identity.
140
+
141
+ Configured `contentTypes[].searchBoost` is a separate local ranking signal.
142
+ `1` is neutral; `0.5..2` maps to a bounded `-0.05..+0.05` contribution, and
143
+ all auxiliary signals share `±0.08`. It cannot create candidates or bypass hard
144
+ filters. Use `gno query --explain`, `gno ask --explain`, or
145
+ `gno query diagnose` when the ranking effect matters; normal output omits the
146
+ boost receipt.
147
+
128
148
  Do not treat MCP/SDK/REST `projectHints` as paths. They are opaque, untrusted,
129
149
  limited to 16, never trigger filesystem probing, and currently produce zero
130
150
  affinity. Explain uses redacted aliases only. Diagnose preserves exact closed
@@ -0,0 +1 @@
1
+ 3da63d624c5d61f121c5082cd5db2b233e95be5c72beba14f4a3e73a14384e02 gno-browser-clipper-v1.27.0.zip
@@ -21,5 +21,5 @@
21
21
  "content_security_policy": {
22
22
  "extension_pages": "script-src 'self'; object-src 'none'; connect-src http://127.0.0.1:*"
23
23
  },
24
- "version": "1.25.1"
24
+ "version": "1.27.0"
25
25
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gmickel/gno",
3
- "version": "1.25.1",
3
+ "version": "1.27.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
@@ -65,6 +65,10 @@ equivalent files fail closed as ambiguous.
65
65
  | status | yes | no | no | yes | no | terminal |
66
66
  | init | no | no | no | no | no | terminal |
67
67
  | setup | yes | no | no | no | no | terminal |
68
+ | profile check | yes | no | no | no | no | terminal |
69
+ | profile show | yes | no | no | no | no | terminal |
70
+ | profile diff | yes | no | no | no | no | terminal |
71
+ | profile apply | yes | no | no | no | no | terminal |
68
72
  | collection add | no | no | no | no | no | terminal |
69
73
  | collection list | yes | no | no | yes | no | terminal |
70
74
  | collection remove | no | no | no | no | no | terminal |
@@ -125,6 +129,89 @@ equivalent files fail closed as ambiguous.
125
129
 
126
130
  ## Commands
127
131
 
132
+ ### gno profile
133
+
134
+ Inspect a repository-owned `.gno/index.yml` retrieval profile without changing
135
+ the user config, index database, model cache, or tracked files.
136
+
137
+ **Synopsis:**
138
+
139
+ ```bash
140
+ gno profile check [path] [--json]
141
+ gno profile show [path] [--json]
142
+ gno profile diff [path] [--json]
143
+ gno profile apply [path] [--json]
144
+ ```
145
+
146
+ With no path, discovery starts at the canonical current directory and walks
147
+ upward. Each directory is checked before its parent, so the nearest nested
148
+ profile wins and any ancestor profile is reported as shadowed; profiles are
149
+ never merged. Discovery stops after checking the first Git root (`.git` may be a
150
+ directory or a worktree file), before crossing a filesystem device boundary,
151
+ or at the filesystem root. This gives a nested repository precedence over its
152
+ parent repository and lets a monorepo subtree intentionally shadow the root
153
+ profile.
154
+
155
+ An explicit directory path is an exact profile-root override: only
156
+ `<path>/.gno/index.yml` is considered. An explicit
157
+ `<path>/.gno/index.yml` file selects that exact profile. Explicit overrides do
158
+ not fall back to ancestors. The profile file and its `.gno` path must resolve
159
+ inside the selected canonical profile root; symlink escapes fail closed.
160
+ Remote callers cannot enable discovery or cause filesystem probes.
161
+
162
+ `check` validates discovery, schema, referenced paths, local preset aliases,
163
+ and, with global `--offline`, exact cache availability without downloading.
164
+ `show` returns the same receipt plus normalized portable desired state. `diff`
165
+ compares that desired state with the selected user config. It reports stale
166
+ same-name/path mappings and explicit repair/removal choices but never applies
167
+ either choice. A missing user config is treated as empty desired-state input;
168
+ an unreadable or invalid config is an actionable validation diagnostic.
169
+
170
+ The three read-only JSON forms use
171
+ [`project-profile-command@1.0`](./output-schemas/project-profile-command.schema.json).
172
+ Receipts contain no absolute profile, config, database, cache, or model paths,
173
+ no timestamps, and no model URIs. Diagnostics and changes are canonically
174
+ ordered, so identical local state produces byte-identical JSON.
175
+
176
+ `apply` rebuilds the shared diff against config reloaded inside a cross-process
177
+ runtime lock, then creates or updates only resources declared by the profile
178
+ through a resumable operation. It can initialize a missing user config. Omitted collections,
179
+ collection-scoped contexts, and content-type rules remain untouched; stale
180
+ same-path collections are reported as skipped and retained. A stale same-name
181
+ collection root is repaired in place without deleting its collection or index
182
+ identity. Apply also updates a timestamp-free `projectProfileBindings` record
183
+ in the local user config with the canonical absolute profile path, profile
184
+ fingerprint, and projected collection. The public `profile_binding` resource
185
+ receipt identifies only the collection and never exposes that local path.
186
+ Model preset aliases resolve to collection-local model overrides.
187
+ Apply synchronizes the config projection but does not index documents; changed
188
+ collections appear in `pendingIndexing`.
189
+ `affinityDefaults` remains profile-scoped and is compiled at trusted local
190
+ retrieval time; apply does not overwrite the user config `projectAffinity`
191
+ default. Its apply resource is therefore `project_affinity/profile/skipped`,
192
+ while the nearest valid profile can still supply request-local affinity.
193
+
194
+ The deterministic JSON result uses
195
+ [`project-profile-apply@1.0`](./output-schemas/project-profile-apply.schema.json).
196
+ Its created/reused/updated/skipped resource receipt is also atomically saved as
197
+ `project-profiles/apply-receipt.json` under the user data directory. The config,
198
+ index, receipt, and lock paths must all remain outside the selected profile
199
+ root. The tracked `.gno/index.yml` is never written. Interrupted or concurrent
200
+ applies resume from fresh config state and converge idempotently.
201
+
202
+ **Exit Codes:**
203
+
204
+ - `0`: profile found and valid (`diff` may still report changes)
205
+ - `1`: profile missing, ambiguous discovery could not be resolved safely, or
206
+ profile/config validation failed, including runtime-path overlap
207
+ - `2`: unexpected local I/O, lock, receipt, or index-store failure
208
+
209
+ `gno setup` calls the same local `check` composition before its folder
210
+ transaction. Inspection is read-only and non-fatal. Plain setup prints bounded
211
+ preview/apply guidance but preserves the existing setup result contract.
212
+ Explicit `--apply-profile` runs the same lock-safe apply path before lexical
213
+ setup and emits `setup-profile-result@1.0`.
214
+
128
215
  ### gno status
129
216
 
130
217
  Display index status and health information.
@@ -349,7 +436,14 @@ Zod validates `id`, `prefixes`, `preset`, `graphHints`, `searchBoost`, and
349
436
  `temporal`, while `preset` remains a permissive string. Post-parse normalization
350
437
  warns and drops unknown preset references, dedupes exact duplicate prefixes,
351
438
  retains overlapping prefixes, and sorts rules longest-prefix-first. `searchBoost`
352
- is accepted but currently no-op. `graphHints` is active: ordered hints type
439
+ defaults to neutral `1`, accepts `0.5..2`, and maps one canonical configured
440
+ type to a bounded `-0.05..+0.05` ranking contribution. A frontmatter type ID
441
+ wins over longest-prefix matching; boosts never stack, cannot create
442
+ candidates, never widen retrieval or defer `minScore`, and share the final
443
+ `±0.08` auxiliary cap with project affinity. Hybrid applies the composed score
444
+ to normalized fusion before rerank blending; rerank order and lexical top-hit
445
+ protection remain authoritative.
446
+ `graphHints` is active: ordered hints type
353
447
  projected wiki/markdown edges and surface in graph traversal/diagnose metadata.
354
448
 
355
449
  ---
@@ -365,7 +459,7 @@ to one standalone background worker and never delays lexical success.
365
459
  ```bash
366
460
  gno setup <folder> [-n|--name <name>] [--exclude <pattern>]...
367
461
  [--authorize-secret-risk] [--connector <id>]...
368
- [--no-semantic] [--json]
462
+ [--apply-profile] [--no-semantic] [--json]
369
463
  ```
370
464
 
371
465
  **Options:**
@@ -376,6 +470,7 @@ gno setup <folder> [-n|--name <name>] [--exclude <pattern>]...
376
470
  | `--exclude <pattern>` | repeatable | core defaults | One literal exclusion per occurrence; never CSV |
377
471
  | `--authorize-secret-risk` | boolean | false | Explicitly authorize likely credentials, private keys, or env files |
378
472
  | `--connector <id>` | repeatable | none | Install or reuse and verify one supported connector after lexical proof |
473
+ | `--apply-profile` | boolean | false | Apply a valid discovered project profile before lexical setup |
379
474
  | `--no-semantic` | boolean | false | Prove lexical retrieval but record semantic work as skipped |
380
475
  | `--json` | boolean | false | Emit one closed setup result object |
381
476
 
@@ -392,6 +487,53 @@ exact `activation.evidence.resultUri`. Terminal stage progress uses stderr;
392
487
  `--quiet` suppresses progress but not the final result. JSON writes exactly one
393
488
  canonical result to stdout on both success and domain failure, with no progress.
394
489
 
490
+ Before the folder transaction, setup performs the same local read-only
491
+ `gno profile check` composition from the supplied folder. Missing and invalid
492
+ profiles remain optional and never block ordinary setup. Terminal output shows
493
+ a valid profile fingerprint plus `profile diff`/`--apply-profile` guidance, or
494
+ an invalid-profile diagnostic, before setup mutates local state.
495
+
496
+ `--apply-profile` is explicit. When the check is valid, setup runs the existing
497
+ cross-process lock-safe, create/update-only `profile apply` path first, then
498
+ uses the applied profile collection's canonical root, name, and filters for
499
+ lexical setup. A nested folder invocation therefore indexes the declared
500
+ profile root rather than creating a duplicate subdirectory collection. The
501
+ profile never deletes omitted resources or overwrites the user-level
502
+ `projectAffinity` default.
503
+
504
+ Once a valid profile has been discovered for an explicit `--apply-profile`
505
+ request, apply is a fail-closed prerequisite. A validation failure returns exit
506
+ 1; an apply I/O/lock/store failure, thrown apply transport, missing result, or
507
+ malformed success receipt returns exit 2. In every case setup aborts before its
508
+ folder transaction or connector work. A late apply failure may have persisted
509
+ resumable create/update-only profile state, but cannot trigger ordinary setup
510
+ reconciliation. The outer result is `failed`, the nested lexical error code is
511
+ `profile_apply_failed`, and `profile.apply` retains a returned apply result or
512
+ is `null` when apply produced no result.
513
+
514
+ Missing or invalid profile inspection remains the optional fallback described
515
+ below. A thrown inspection transport/runtime failure for an explicit
516
+ `--apply-profile` request instead returns exit 2 with
517
+ `profile_inspection_failed` before apply or setup mutation. Because no trusted
518
+ profile check result exists, this failure uses the unchanged
519
+ `setup-command-result@1.0` shape rather than fabricating `profile.check`.
520
+
521
+ For a valid profile, `--apply-profile` is mutually exclusive with explicit
522
+ `--name` and `--exclude` values. A conflict returns exit 1 with
523
+ `profile_option_conflict` before config, store, or index mutation. Profile
524
+ include/exclude values use validated Bun-glob semantics; plain exclusion
525
+ components retain component matching. Brace alternatives are rejected; express
526
+ their branches as separate include/exclude entries. Discovery permission/I/O
527
+ failures return exit 2, while missing, disabled, invalid, and unsafe profiles
528
+ return exit 1.
529
+
530
+ Opt-in JSON uses
531
+ [`setup-profile-result@1.0`](./output-schemas/setup-profile-result.schema.json)
532
+ and includes the closed `profile.check`, nullable `profile.apply`, unchanged
533
+ setup result, and connectors. A missing/invalid profile keeps setup usable and
534
+ returns `completed_with_actions` with `profile.apply: null`. Without
535
+ `--apply-profile`, the existing setup/activation JSON bytes remain unchanged.
536
+
395
537
  After lexical proof, the command records one private atomic
396
538
  `setup-semantic@1.0` receipt per canonical index/folder and starts one detached,
397
539
  collection-scoped Bun worker. A matching live worker is reused; a dead worker is
@@ -430,6 +572,7 @@ second connector fingerprint or cache.
430
572
 
431
573
  - [`setup-command-result@1.0`](./output-schemas/setup-command-result.schema.json)
432
574
  - [`setup-activation-result@1.0`](./output-schemas/setup-activation-result.schema.json)
575
+ - [`setup-profile-result@1.0`](./output-schemas/setup-profile-result.schema.json)
433
576
  - [`setup-semantic@1.0`](./output-schemas/setup-semantic-receipt.schema.json)
434
577
  - [`FolderSetupReceipt@1.0`](./output-schemas/setup-receipt.schema.json)
435
578
 
@@ -1067,7 +1210,7 @@ Human-friendly query with citations-first output and optional grounded answer.
1067
1210
  **Synopsis:**
1068
1211
 
1069
1212
  ```bash
1070
- gno ask <query> [-n <num>] [-c <collection>] [--lang <bcp47>] [--since <date>] [--until <date>] [--category <values>] [--author <text>] [--intent <text>] [--exclude <values>] [--query-mode <mode:text>]... [-C <num>] [--answer|--verify] [--no-answer] [--max-answer-tokens <n>] [--context-budget-tokens <n>] [--context-budget-bytes <n>] [--min-score <score>] [--graph] [--no-expand] [--no-rerank] [--show-sources] [--json|--md]
1213
+ gno ask <query> [-n <num>] [-c <collection>] [--lang <bcp47>] [--since <date>] [--until <date>] [--category <values>] [--author <text>] [--intent <text>] [--exclude <values>] [--query-mode <mode:text>]... [-C <num>] [--answer|--verify] [--no-answer] [--max-answer-tokens <n>] [--context-budget-tokens <n>] [--context-budget-bytes <n>] [--min-score <score>] [--graph] [--no-expand] [--no-rerank] [--explain] [--show-sources] [--json|--md]
1071
1214
  ```
1072
1215
 
1073
1216
  **Options:**
@@ -1092,6 +1235,7 @@ gno ask <query> [-n <num>] [-c <collection>] [--lang <bcp47>] [--since <date>] [
1092
1235
  | `-C, --candidate-limit` | integer | 20 | Max candidates passed to reranking |
1093
1236
  | `--no-expand` | boolean | false | Disable query expansion |
1094
1237
  | `--no-rerank` | boolean | false | Disable cross-encoder reranking |
1238
+ | `--explain` | boolean | false | Include retrieval scoring details; prints to stderr outside structured output |
1095
1239
  | `--show-sources` | boolean | false | Show all retrieved sources (not just cited) |
1096
1240
  | `--project-root` | string[] | cwd | Trusted project root; repeatable, replaces default cwd/repository affinity |
1097
1241
  | `--no-project-affinity` | boolean | false | Disable project-aware soft ranking; invalid with `--project-root` |
@@ -1102,6 +1246,11 @@ See [Output Schemas](./output-schemas/ask.schema.json)
1102
1246
  Notes:
1103
1247
 
1104
1248
  - `meta.answerContext` is optional explain payload for answer source selection.
1249
+ - `meta.explain` is present only with `--explain`. Its optional
1250
+ `contentTypeBoost` result component contains the raw/base score, configured
1251
+ factor, capped and combined contributions, final score, rule source, and full
1252
+ ranking-rules fingerprint. Verified Ask attaches this as a non-canonical
1253
+ sidecar; Capsule identity and bytes do not change.
1105
1254
  - `--verify` implies answer generation and cannot be combined with
1106
1255
  `--no-answer`. The JSON result adds the closed Capsule, freshness receipt,
1107
1256
  four-state per-claim verdicts (`supported`, `contradicted`, `insufficient`,
@@ -1338,6 +1487,10 @@ retrieval results and is used as trusted guidance during grounded answer
1338
1487
  generation. Matching scopes compose once in this order: global, collection,
1339
1488
  then path prefixes from broadest to most specific. Context guides interpretation;
1340
1489
  it is not searched and does not change ranking.
1490
+ Multiple distinct normalized texts may share one scope. The persisted identity
1491
+ is `(scopeType, canonicalScopeKey, normalizedText)`. Text normalization removes
1492
+ a leading BOM, converts CRLF/CR to LF, applies NFC, and trims surrounding
1493
+ whitespace; an exact normalized duplicate is rejected.
1341
1494
 
1342
1495
  **Synopsis:**
1343
1496
 
@@ -1411,18 +1564,20 @@ gno context check [--json|--md]
1411
1564
 
1412
1565
  ### gno context rm
1413
1566
 
1414
- Remove a context.
1567
+ Remove a context. Scope-only removal succeeds only when exactly one record
1568
+ matches. If multiple texts share the scope, the caller MUST pass exact text;
1569
+ ambiguous removal fails without mutation.
1415
1570
 
1416
1571
  **Synopsis:**
1417
1572
 
1418
1573
  ```bash
1419
- gno context rm <scope>
1574
+ gno context rm <scope> [text]
1420
1575
  ```
1421
1576
 
1422
1577
  **Exit Codes:**
1423
1578
 
1424
1579
  - 0: Success
1425
- - 1: Scope not found
1580
+ - 1: Invalid/not-found scope, text not found, or ambiguous scope-only removal
1426
1581
 
1427
1582
  ---
1428
1583
 
@@ -61,7 +61,7 @@ CREATE TABLE IF NOT EXISTS contexts (
61
61
  scope_key TEXT NOT NULL,
62
62
  text TEXT NOT NULL,
63
63
  synced_at TEXT NOT NULL DEFAULT (datetime('now')),
64
- PRIMARY KEY (scope_type, scope_key)
64
+ PRIMARY KEY (scope_type, scope_key, text)
65
65
  );
66
66
 
67
67
  -- ─────────────────────────────────────────────────────────────────────────────
@@ -26,6 +26,7 @@ evals/agentic/
26
26
  project-affinity-outcome.ts
27
27
  project-affinity-promotion.ts
28
28
  project-affinity-runtime.ts
29
+ content-type-boost-promotion.ts
29
30
  verified-ask-outcome.ts
30
31
  verified-ask-promotion.ts
31
32
  demos/context-capsule.ts
@@ -103,6 +104,22 @@ receipts, and compares the committed artifact with a fresh deterministic
103
104
  production run. The controlled synthetic lane isolates the score seam and makes
104
105
  no general workload superiority claim.
105
106
 
107
+ ## Separate content-type boost promotion
108
+
109
+ The authoritative lane also writes
110
+ `content-type-boost-promotion.json` and `.md`. These 24 before/after receipts
111
+ project the fn-97 production retrieval rankings through the shipped
112
+ content-type ranking seam with no configured rules. Every ordered URI and
113
+ required-evidence receipt must remain byte-identical, with zero accuracy and
114
+ coverage loss. This is backward-compatibility evidence for existing configs,
115
+ not an active-rule quality claim.
116
+
117
+ Active positive/negative factors, keyword stuffing, deterministic ties,
118
+ configured-ID versus prefix conflicts, filter isolation, and project-affinity
119
+ composition are gated separately by the deterministic adversarial pipeline
120
+ suite. Egress policy is not yet an available retrieval capability, so the
121
+ artifact makes no egress-enforcement claim.
122
+
106
123
  The first fixture version contains 24 original synthetic tasks and 34 Markdown
107
124
  documents under the MIT license. It covers exact identifiers, ambiguity,
108
125
  multi-document comparisons, meeting decisions, temporal questions, typed
package/spec/mcp.md CHANGED
@@ -216,7 +216,7 @@ Required input:
216
216
  Optional fields are `collection`, `limit` (default 5), `minScore`, `lang`,
217
217
  `intent`, `candidateLimit`, `exclude`, `queryModes`, `tagsAll`, `tagsAny`,
218
218
  `since`, `until`, `categories`, `author`, `graph`, `noGraph`, `noRerank`,
219
- `maxAnswerTokens`, `contextBudgetTokens`, and `contextBudgetBytes`. Input
219
+ `explain`, `maxAnswerTokens`, `contextBudgetTokens`, and `contextBudgetBytes`. Input
220
220
  objects are closed.
221
221
  `projectHints` is an optional array of at most 16 non-empty caller hints. Hints
222
222
  are normalized and deduplicated as opaque values, never resolved against or
@@ -648,6 +648,11 @@ Hybrid search combining BM25 and vector retrieval with optional expansion and re
648
648
  "description": "Enable cross-encoder reranking",
649
649
  "default": true
650
650
  },
651
+ "explain": {
652
+ "type": "boolean",
653
+ "description": "Include deterministic stage and per-result scoring metadata",
654
+ "default": false
655
+ },
651
656
  "noGraph": {
652
657
  "type": "boolean",
653
658
  "description": "Compatibility no-op unless graph is also true",
@@ -692,6 +697,11 @@ Search result items include `contentType` when available and always include
692
697
  human-oriented; structured clients should read `structuredContent.results`.
693
698
  Structured result items also preserve optional `context` guidance in
694
699
  global-to-specific order without changing the result `uri` or `docid`.
700
+ When `explain: true`, `structuredContent.meta.explain` includes deterministic
701
+ stage lines and per-result score receipts. Non-neutral configured content-type
702
+ rules add `contentTypeBoost` with base/raw scores, factor, capped contribution,
703
+ shared auxiliary-cap composition, final score, rule source, and redacted rules
704
+ fingerprint. Normal output omits this sidecar.
695
705
 
696
706
  Compatibility / migration notes:
697
707
 
@@ -753,16 +763,17 @@ plus a required `target` reference.
753
763
  - `target`: URI, `#docid`, or `collection/path` for the document to diagnose.
754
764
  - `query`, filters, `queryModes`, `fast`/`thorough`, `graph`, and rerank/expand controls behave like `gno_query`.
755
765
 
756
- **Output Schema:** `gno://schemas/query-diagnose@1.0`
766
+ **Output Schema:** `gno://schemas/query-diagnose@1.2`
757
767
 
758
768
  Structured content includes `schemaVersion`, normalized `query`, `target`
759
769
  metadata/status (`not_found`, `inactive`, `no_indexed_content`,
760
770
  `filtered_out`, or `diagnosed`), `stages` for BM25/vector/fusion/graph/rerank,
761
771
  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.
772
+ MCP inputs are remote and untrusted, so this tool omits `affinity`, even when
773
+ `projectHints` are supplied. Neutral configurations preserve exact v1.0 bytes;
774
+ an active configured content-type boost emits v1.2 with the same bounded score
775
+ receipt exposed by query explain. The v1.1 affinity-bearing branch remains
776
+ reserved for trusted local CLI diagnose requests.
766
777
 
767
778
  Use when an expected target is missing from `gno_query`, when filters may have
768
779
  excluded it, or when an agent needs evidence before raising `candidateLimit`,
@@ -979,11 +990,19 @@ counters; it never claims attachment to another process.
979
990
  "totalDocuments": 150,
980
991
  "totalChunks": 800,
981
992
  "embeddingBacklog": 0,
993
+ "contentTypeBoost": {
994
+ "rulesFingerprint": "<sha256>",
995
+ "rules": [{ "id": "decision", "searchBoost": 2 }]
996
+ },
982
997
  "healthy": true
983
998
  }
984
999
  }
985
1000
  ```
986
1001
 
1002
+ `contentTypeBoost` is a redacted ranking-status projection. It exposes only
1003
+ normalized IDs/factors plus the rules fingerprint; path prefixes are never
1004
+ returned.
1005
+
987
1006
  ---
988
1007
 
989
1008
  ### gno_capture
@@ -557,6 +557,9 @@
557
557
  }
558
558
  }
559
559
  }
560
+ },
561
+ "explain": {
562
+ "$ref": "gno://schemas/search-results@1.0#/properties/meta/properties/explain"
560
563
  }
561
564
  }
562
565
  }