@gmickel/gno 1.21.0 → 1.23.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 (47) hide show
  1. package/README.md +26 -2
  2. package/assets/skill/SKILL.md +15 -0
  3. package/package.json +2 -1
  4. package/spec/cli.md +80 -20
  5. package/spec/evals-agentic.md +83 -0
  6. package/spec/evals.md +6 -0
  7. package/spec/mcp.md +18 -0
  8. package/spec/output-schemas/publish-artifact.schema.json +284 -0
  9. package/spec/output-schemas/query-diagnose-v1.schema.json +123 -0
  10. package/spec/output-schemas/query-diagnose.schema.json +89 -2
  11. package/src/app/context-runtime-types.ts +3 -0
  12. package/src/app/context-runtime.ts +1 -0
  13. package/src/app/context-surface.ts +4 -2
  14. package/src/cli/commands/ask.ts +31 -20
  15. package/src/cli/commands/context-build.ts +17 -7
  16. package/src/cli/commands/query.ts +58 -37
  17. package/src/cli/commands/search.ts +29 -19
  18. package/src/cli/commands/vsearch.ts +31 -22
  19. package/src/cli/options.ts +39 -0
  20. package/src/cli/program.ts +48 -0
  21. package/src/config/defaults.ts +10 -1
  22. package/src/config/types.ts +71 -0
  23. package/src/core/project-affinity-surface.ts +114 -0
  24. package/src/core/project-affinity.ts +330 -0
  25. package/src/core/validation.ts +20 -1
  26. package/src/mcp/tools/ask.ts +10 -1
  27. package/src/mcp/tools/context.ts +18 -0
  28. package/src/mcp/tools/index.ts +13 -2
  29. package/src/mcp/tools/query.ts +12 -0
  30. package/src/mcp/tools/search.ts +7 -0
  31. package/src/mcp/tools/vsearch.ts +7 -0
  32. package/src/pipeline/diagnose.ts +48 -3
  33. package/src/pipeline/explain.ts +54 -13
  34. package/src/pipeline/hybrid.ts +100 -59
  35. package/src/pipeline/project-affinity.ts +162 -0
  36. package/src/pipeline/search.ts +76 -10
  37. package/src/pipeline/types.ts +9 -0
  38. package/src/pipeline/vsearch.ts +117 -91
  39. package/src/publish/artifact-validation.ts +259 -0
  40. package/src/publish/artifact.ts +234 -118
  41. package/src/publish/export-service.ts +5 -9
  42. package/src/publish/metadata.ts +195 -0
  43. package/src/sdk/client.ts +80 -20
  44. package/src/sdk/index.ts +2 -0
  45. package/src/sdk/types.ts +20 -7
  46. package/src/serve/context-capsule.ts +18 -1
  47. package/src/serve/routes/api.ts +69 -0
@@ -0,0 +1,284 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "gno://schemas/publish-artifact@1.0",
4
+ "title": "GNO publish artifact",
5
+ "oneOf": [
6
+ { "$ref": "#/definitions/artifactV1" },
7
+ { "$ref": "#/definitions/artifactV2" }
8
+ ],
9
+ "definitions": {
10
+ "artifactV1": {
11
+ "type": "object",
12
+ "additionalProperties": false,
13
+ "required": ["version", "source", "exportedAt", "spaces"],
14
+ "properties": {
15
+ "version": { "const": 1 },
16
+ "source": { "$ref": "#/definitions/slug" },
17
+ "exportedAt": { "type": "string", "format": "date-time" },
18
+ "spaces": {
19
+ "type": "array",
20
+ "minItems": 1,
21
+ "items": {
22
+ "oneOf": [
23
+ { "$ref": "#/definitions/publicSpace" },
24
+ { "$ref": "#/definitions/restrictedSpace" }
25
+ ]
26
+ }
27
+ }
28
+ }
29
+ },
30
+ "artifactV2": {
31
+ "type": "object",
32
+ "additionalProperties": false,
33
+ "required": ["version", "source", "exportedAt", "spaces"],
34
+ "properties": {
35
+ "version": { "const": 2 },
36
+ "source": { "$ref": "#/definitions/slug" },
37
+ "exportedAt": { "type": "string", "format": "date-time" },
38
+ "spaces": {
39
+ "type": "array",
40
+ "minItems": 1,
41
+ "items": { "$ref": "#/definitions/encryptedSpace" }
42
+ }
43
+ }
44
+ },
45
+ "slug": {
46
+ "type": "string",
47
+ "pattern": "^[a-z0-9](?:[a-z0-9-]{0,78}[a-z0-9])?$",
48
+ "maxLength": 80
49
+ },
50
+ "hash": {
51
+ "type": "string",
52
+ "pattern": "^[a-f0-9]{64}$"
53
+ },
54
+ "docid": {
55
+ "type": "string",
56
+ "pattern": "^#[a-f0-9]{8}$"
57
+ },
58
+ "metadata": {
59
+ "type": "object",
60
+ "additionalProperties": {
61
+ "oneOf": [
62
+ { "type": "string" },
63
+ {
64
+ "type": "array",
65
+ "items": { "type": "string" }
66
+ }
67
+ ]
68
+ }
69
+ },
70
+ "note": {
71
+ "type": "object",
72
+ "additionalProperties": false,
73
+ "required": ["markdown", "slug", "summary", "title"],
74
+ "properties": {
75
+ "markdown": { "type": "string" },
76
+ "metadata": { "$ref": "#/definitions/metadata" },
77
+ "slug": { "$ref": "#/definitions/slug" },
78
+ "summary": { "type": "string" },
79
+ "title": { "type": "string", "minLength": 1 }
80
+ }
81
+ },
82
+ "publicSpace": {
83
+ "type": "object",
84
+ "additionalProperties": false,
85
+ "required": [
86
+ "notes",
87
+ "routeSlug",
88
+ "sourceType",
89
+ "summary",
90
+ "title",
91
+ "visibility",
92
+ "manifest"
93
+ ],
94
+ "properties": {
95
+ "homeNoteSlug": { "$ref": "#/definitions/slug" },
96
+ "notes": {
97
+ "type": "array",
98
+ "minItems": 1,
99
+ "items": { "$ref": "#/definitions/note" }
100
+ },
101
+ "routeSlug": { "$ref": "#/definitions/slug" },
102
+ "sourceType": { "enum": ["note", "collection"] },
103
+ "summary": { "type": "string" },
104
+ "title": { "type": "string", "minLength": 1 },
105
+ "visibility": { "const": "public" },
106
+ "manifest": { "$ref": "#/definitions/publicManifest" }
107
+ }
108
+ },
109
+ "restrictedSpace": {
110
+ "type": "object",
111
+ "additionalProperties": false,
112
+ "required": [
113
+ "notes",
114
+ "routeSlug",
115
+ "sourceType",
116
+ "summary",
117
+ "title",
118
+ "visibility"
119
+ ],
120
+ "properties": {
121
+ "homeNoteSlug": { "$ref": "#/definitions/slug" },
122
+ "notes": {
123
+ "type": "array",
124
+ "minItems": 1,
125
+ "items": { "$ref": "#/definitions/note" }
126
+ },
127
+ "routeSlug": { "$ref": "#/definitions/slug" },
128
+ "sourceType": { "enum": ["note", "collection"] },
129
+ "summary": { "type": "string" },
130
+ "title": { "type": "string", "minLength": 1 },
131
+ "visibility": { "enum": ["secret-link", "invite-only"] }
132
+ }
133
+ },
134
+ "publicManifest": {
135
+ "type": "object",
136
+ "additionalProperties": false,
137
+ "required": [
138
+ "schemaVersion",
139
+ "projectionRevision",
140
+ "generatedAt",
141
+ "visibility",
142
+ "capabilities",
143
+ "documents"
144
+ ],
145
+ "properties": {
146
+ "schemaVersion": { "const": "1.0" },
147
+ "projectionRevision": { "$ref": "#/definitions/hash" },
148
+ "generatedAt": { "type": "string", "format": "date-time" },
149
+ "visibility": { "const": "public" },
150
+ "capabilities": {
151
+ "type": "object",
152
+ "additionalProperties": false,
153
+ "required": [
154
+ "capsuleEvidence",
155
+ "exactLineCitations",
156
+ "llmsTxt",
157
+ "markdownDocuments"
158
+ ],
159
+ "properties": {
160
+ "capsuleEvidence": { "const": true },
161
+ "exactLineCitations": { "const": true },
162
+ "llmsTxt": { "const": true },
163
+ "markdownDocuments": { "const": true }
164
+ }
165
+ },
166
+ "documents": {
167
+ "type": "array",
168
+ "minItems": 1,
169
+ "items": { "$ref": "#/definitions/publicDocument" }
170
+ }
171
+ }
172
+ },
173
+ "publicDocument": {
174
+ "type": "object",
175
+ "additionalProperties": false,
176
+ "required": [
177
+ "slug",
178
+ "title",
179
+ "summary",
180
+ "markdownPath",
181
+ "contentHash",
182
+ "byteLength",
183
+ "lineCount",
184
+ "evidence"
185
+ ],
186
+ "properties": {
187
+ "slug": { "$ref": "#/definitions/slug" },
188
+ "title": { "type": "string", "minLength": 1 },
189
+ "summary": { "type": "string" },
190
+ "markdownPath": {
191
+ "type": "string",
192
+ "pattern": "^\\./[a-z0-9](?:[a-z0-9-]{0,78}[a-z0-9])?\\.md$"
193
+ },
194
+ "contentHash": { "$ref": "#/definitions/hash" },
195
+ "byteLength": { "type": "integer", "minimum": 0 },
196
+ "lineCount": { "type": "integer", "minimum": 1 },
197
+ "evidence": { "$ref": "#/definitions/publicEvidence" }
198
+ }
199
+ },
200
+ "publicEvidence": {
201
+ "type": "object",
202
+ "additionalProperties": false,
203
+ "required": [
204
+ "evidenceId",
205
+ "uri",
206
+ "docid",
207
+ "startLine",
208
+ "endLine",
209
+ "sourceHash",
210
+ "mirrorHash",
211
+ "passageHash",
212
+ "locator"
213
+ ],
214
+ "properties": {
215
+ "evidenceId": { "$ref": "#/definitions/hash" },
216
+ "uri": {
217
+ "type": "string",
218
+ "pattern": "^gno://public/[a-z0-9][a-z0-9-]{0,79}/[a-z0-9][a-z0-9-]{0,79}\\.md$"
219
+ },
220
+ "docid": { "$ref": "#/definitions/docid" },
221
+ "startLine": { "const": 1 },
222
+ "endLine": { "type": "integer", "minimum": 1 },
223
+ "sourceHash": { "$ref": "#/definitions/hash" },
224
+ "mirrorHash": { "$ref": "#/definitions/hash" },
225
+ "passageHash": { "$ref": "#/definitions/hash" },
226
+ "locator": {
227
+ "type": "string",
228
+ "pattern": "^\\./[a-z0-9][a-z0-9-]{0,79}\\.md#L1-L[1-9][0-9]*$"
229
+ }
230
+ }
231
+ },
232
+ "encryptedSpace": {
233
+ "type": "object",
234
+ "additionalProperties": false,
235
+ "required": [
236
+ "encryptedPayload",
237
+ "routeSlug",
238
+ "secretToken",
239
+ "sourceType",
240
+ "visibility"
241
+ ],
242
+ "properties": {
243
+ "encryptedPayload": {
244
+ "type": "object",
245
+ "additionalProperties": false,
246
+ "required": ["ciphertext", "iterations", "iv", "salt"],
247
+ "properties": {
248
+ "ciphertext": {
249
+ "type": "string",
250
+ "minLength": 1,
251
+ "maxLength": 67108864,
252
+ "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"
253
+ },
254
+ "iterations": {
255
+ "type": "integer",
256
+ "minimum": 1,
257
+ "maximum": 9007199254740991
258
+ },
259
+ "iv": {
260
+ "type": "string",
261
+ "minLength": 1,
262
+ "maxLength": 1024,
263
+ "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"
264
+ },
265
+ "salt": {
266
+ "type": "string",
267
+ "minLength": 1,
268
+ "maxLength": 1024,
269
+ "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"
270
+ }
271
+ }
272
+ },
273
+ "routeSlug": { "$ref": "#/definitions/slug" },
274
+ "secretToken": {
275
+ "type": "string",
276
+ "minLength": 1,
277
+ "maxLength": 512
278
+ },
279
+ "sourceType": { "enum": ["note", "collection"] },
280
+ "visibility": { "const": "encrypted" }
281
+ }
282
+ }
283
+ }
284
+ }
@@ -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
+ }
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
- "$id": "gno://schemas/query-diagnose@1.0",
3
+ "$id": "gno://schemas/query-diagnose@1.1",
4
4
  "title": "GNO Query Diagnose",
5
5
  "type": "object",
6
6
  "required": ["schemaVersion", "query", "target", "stages", "chunk", "meta"],
7
7
  "properties": {
8
- "schemaVersion": { "type": "string", "const": "1.0" },
8
+ "schemaVersion": { "type": "string", "enum": ["1.0", "1.1"] },
9
9
  "query": { "type": "string" },
10
10
  "target": {
11
11
  "type": "object",
@@ -86,6 +86,74 @@
86
86
  "additionalProperties": false
87
87
  }
88
88
  },
89
+ "affinity": {
90
+ "type": "object",
91
+ "required": [
92
+ "affinityAdjustedScore",
93
+ "affinityApplied",
94
+ "affinityRequested",
95
+ "affinityWeight",
96
+ "baseScore",
97
+ "collectionAlias",
98
+ "combinedAuxiliaryApplied",
99
+ "combinedAuxiliaryCap",
100
+ "combinedAuxiliaryRequested",
101
+ "finalBlendedScore",
102
+ "finalScore",
103
+ "matched",
104
+ "rawScore",
105
+ "rawScoreKind",
106
+ "rootAlias",
107
+ "source"
108
+ ],
109
+ "properties": {
110
+ "affinityAdjustedScore": {
111
+ "type": "number",
112
+ "minimum": 0,
113
+ "maximum": 1
114
+ },
115
+ "affinityApplied": { "type": "number" },
116
+ "affinityRequested": { "type": "number" },
117
+ "affinityWeight": {
118
+ "type": "number",
119
+ "minimum": 0,
120
+ "maximum": 0.03
121
+ },
122
+ "baseScore": { "type": "number", "minimum": 0, "maximum": 1 },
123
+ "collectionAlias": {
124
+ "type": ["string", "null"],
125
+ "pattern": "^collection_[a-f0-9]{12}$"
126
+ },
127
+ "combinedAuxiliaryApplied": {
128
+ "type": "number",
129
+ "minimum": -0.08,
130
+ "maximum": 0.08
131
+ },
132
+ "combinedAuxiliaryCap": { "type": "number", "const": 0.08 },
133
+ "combinedAuxiliaryRequested": { "type": "number" },
134
+ "finalBlendedScore": {
135
+ "type": "number",
136
+ "minimum": 0,
137
+ "maximum": 1
138
+ },
139
+ "finalScore": { "type": "number", "minimum": 0, "maximum": 1 },
140
+ "matched": { "type": "boolean" },
141
+ "rawScore": { "type": "number" },
142
+ "rawScoreKind": {
143
+ "type": "string",
144
+ "enum": ["bm25", "hybrid_blended", "normalized", "vector_distance"]
145
+ },
146
+ "rootAlias": {
147
+ "type": ["string", "null"],
148
+ "pattern": "^root_[a-f0-9]{12}$"
149
+ },
150
+ "source": {
151
+ "type": ["string", "null"],
152
+ "enum": ["cli_cwd", "cli_explicit", "cli_worktree", null]
153
+ }
154
+ },
155
+ "additionalProperties": false
156
+ },
89
157
  "chunk": {
90
158
  "type": "object",
91
159
  "required": ["seq", "startLine", "endLine", "language"],
@@ -119,5 +187,24 @@
119
187
  "additionalProperties": false
120
188
  }
121
189
  },
190
+ "allOf": [
191
+ {
192
+ "if": {
193
+ "properties": { "schemaVersion": { "const": "1.0" } },
194
+ "required": ["schemaVersion"]
195
+ },
196
+ "then": { "properties": { "affinity": false } }
197
+ },
198
+ {
199
+ "if": {
200
+ "properties": { "schemaVersion": { "const": "1.1" } },
201
+ "required": ["schemaVersion"]
202
+ },
203
+ "then": {
204
+ "properties": { "affinity": {} },
205
+ "required": ["affinity"]
206
+ }
207
+ }
208
+ ],
122
209
  "additionalProperties": false
123
210
  }
@@ -4,6 +4,7 @@ import type { ContextEvidenceCompilerDeps } from "../core/context-evidence";
4
4
  import type { ContextVerifierDeps } from "../core/context-verifier";
5
5
  import type { RetrievalTraceSession } from "../core/retrieval-trace-session";
6
6
  import type { EmbeddingPort, RerankPort } from "../llm/types";
7
+ import type { ProjectAffinityScoringInput } from "../pipeline/project-affinity";
7
8
  import type { QueryModeInput } from "../pipeline/types";
8
9
  import type { StorePort } from "../store/types";
9
10
  import type { VectorIndexPort } from "../store/vector";
@@ -50,6 +51,8 @@ export interface ContextCapsuleRuntimeDeps {
50
51
  countTokens?: (accountingJson: string) => number;
51
52
  tokenizerFingerprint?: string | null;
52
53
  resolveCurrentRanks?: ContextVerifierDeps["resolveCurrentRanks"];
54
+ /** Trusted, already-resolved project affinity; never accepts raw inputs. */
55
+ projectAffinity?: ProjectAffinityScoringInput;
53
56
  /** Optional non-canonical receipt session owned by the calling surface. */
54
57
  traceSession?: RetrievalTraceSession;
55
58
  }
@@ -96,6 +96,7 @@ export const buildContextCapsule = async (
96
96
  {
97
97
  ...request,
98
98
  noRerank: requestNoRerank,
99
+ projectAffinity: deps.projectAffinity,
99
100
  traceSession: deps.traceSession,
100
101
  }
101
102
  );
@@ -44,6 +44,7 @@ export const contextBuildSurfaceSchema = z
44
44
  safetyMarginTokens: nonnegativeInteger.optional(),
45
45
  safetyMarginBytes: nonnegativeInteger.optional(),
46
46
  depthPolicy: z.enum(["fast", "balanced", "thorough"]).optional(),
47
+ projectHints: z.array(z.string()).max(16).optional(),
47
48
  format: z.enum(["json", "md"]).optional(),
48
49
  })
49
50
  .strict();
@@ -60,6 +61,7 @@ export type ContextSurfaceFormat = "json" | "md";
60
61
  export interface ParsedContextBuildSurfaceInput {
61
62
  input: ContextCapsuleBuildInput;
62
63
  format: ContextSurfaceFormat;
64
+ projectHints?: string[];
63
65
  }
64
66
 
65
67
  export interface ParsedContextVerifySurfaceInput {
@@ -117,8 +119,8 @@ export const parseContextBuildSurfaceInput = (
117
119
  ): ParsedContextBuildSurfaceInput => {
118
120
  const parsed = contextBuildSurfaceSchema.safeParse(value);
119
121
  if (!parsed.success) throw invalidInput(parsed.error);
120
- const { format = "json", ...input } = parsed.data;
121
- return { input: { ...input, indexName }, format };
122
+ const { format = "json", projectHints, ...input } = parsed.data;
123
+ return { input: { ...input, indexName }, format, projectHints };
122
124
  };
123
125
 
124
126
  export const parseContextVerifySurfaceInput = (
@@ -5,6 +5,7 @@
5
5
  * @module src/cli/commands/ask
6
6
  */
7
7
 
8
+ import type { CliProjectAffinityRequest } from "../../core/project-affinity-surface";
8
9
  import type { RetrievalTraceSurfaceMetadata } from "../../core/retrieval-trace-session";
9
10
  import type { RetrievalTraceSession } from "../../core/retrieval-trace-session";
10
11
  import type {
@@ -15,6 +16,7 @@ import type {
15
16
  import type { AskOptions, AskResult, Citation } from "../../pipeline/types";
16
17
 
17
18
  import { buildVerifiedAsk } from "../../app/verified-ask";
19
+ import { resolveCliProjectAffinity } from "../../core/project-affinity-surface";
18
20
  import {
19
21
  finishRetrievalTraceAfterError,
20
22
  retrievalTraceFilters,
@@ -46,24 +48,25 @@ export { formatAsk } from "./ask-format";
46
48
  // Types
47
49
  // ─────────────────────────────────────────────────────────────────────────────
48
50
 
49
- export type AskCommandOptions = AskOptions & {
50
- /** Override config path */
51
- configPath?: string;
52
- /** Override embedding model */
53
- embedModel?: string;
54
- /** Override expansion model */
55
- expandModel?: string;
56
- /** Override answer generation model */
57
- genModel?: string;
58
- /** Override rerank model */
59
- rerankModel?: string;
60
- /** Output as JSON */
61
- json?: boolean;
62
- /** Output as Markdown */
63
- md?: boolean;
64
- /** Show all retrieved sources (not just cited) */
65
- showSources?: boolean;
66
- };
51
+ export type AskCommandOptions = Omit<AskOptions, "projectAffinity"> &
52
+ CliProjectAffinityRequest & {
53
+ /** Override config path */
54
+ configPath?: string;
55
+ /** Override embedding model */
56
+ embedModel?: string;
57
+ /** Override expansion model */
58
+ expandModel?: string;
59
+ /** Override answer generation model */
60
+ genModel?: string;
61
+ /** Override rerank model */
62
+ rerankModel?: string;
63
+ /** Output as JSON */
64
+ json?: boolean;
65
+ /** Output as Markdown */
66
+ md?: boolean;
67
+ /** Show all retrieved sources (not just cited) */
68
+ showSources?: boolean;
69
+ };
67
70
 
68
71
  export type AskCommandResult =
69
72
  | {
@@ -108,6 +111,12 @@ export async function ask(
108
111
  let traceSession: RetrievalTraceSession | undefined;
109
112
 
110
113
  try {
114
+ const { projectAffinityDisabled, projectRoots, ...askOptions } = options;
115
+ const projectAffinity = await resolveCliProjectAffinity(config, {
116
+ cwd: process.cwd(),
117
+ disabled: projectAffinityDisabled,
118
+ projectRoots,
119
+ });
111
120
  const verificationRequested = options.verify === true;
112
121
  const answerRequested =
113
122
  verificationRequested || Boolean(options.answer && !options.noAnswer);
@@ -141,7 +150,7 @@ export async function ask(
141
150
  store,
142
151
  config,
143
152
  query,
144
- filters: retrievalTraceFilters({ ...options, limit }),
153
+ filters: retrievalTraceFilters({ ...askOptions, limit }),
145
154
  pipeline: "ask",
146
155
  indexName: globals.index,
147
156
  modelUris: [embedUri, expandUri, answerUri, rerankUri].filter(
@@ -264,7 +273,7 @@ export async function ask(
264
273
  if (verificationRequested && answerPort) {
265
274
  const verified = await buildVerifiedAsk(
266
275
  query,
267
- { ...options, limit },
276
+ { ...askOptions, limit, projectAffinity },
268
277
  {
269
278
  store,
270
279
  config,
@@ -273,6 +282,7 @@ export async function ask(
273
282
  embedPort,
274
283
  rerankPort,
275
284
  genPort: answerPort,
285
+ projectAffinity,
276
286
  traceSession,
277
287
  }
278
288
  );
@@ -308,6 +318,7 @@ export async function ask(
308
318
  noExpand: options.noExpand,
309
319
  noRerank: options.noRerank,
310
320
  candidateLimit: options.candidateLimit,
321
+ projectAffinity,
311
322
  traceSession,
312
323
  });
313
324