@untangle-code/config 0.0.0-stage → 0.1.1
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.
- package/LICENSE +661 -0
- package/NOTICE +90 -0
- package/README.md +262 -2
- package/THIRD_PARTY_LICENSES.md +29 -0
- package/dist/chunker-budget.d.ts +58 -0
- package/dist/chunker-budget.d.ts.map +1 -0
- package/dist/chunker-budget.js +11 -0
- package/dist/chunker-budget.js.map +1 -0
- package/dist/defaults.d.ts +50 -0
- package/dist/defaults.d.ts.map +1 -0
- package/dist/defaults.js +179 -0
- package/dist/defaults.js.map +1 -0
- package/dist/discovery.d.ts +40 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +76 -0
- package/dist/discovery.js.map +1 -0
- package/dist/env.d.ts +37 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +100 -0
- package/dist/env.js.map +1 -0
- package/dist/hash.d.ts +37 -0
- package/dist/hash.d.ts.map +1 -0
- package/dist/hash.js +52 -0
- package/dist/hash.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/load.d.ts +61 -0
- package/dist/load.d.ts.map +1 -0
- package/dist/load.js +264 -0
- package/dist/load.js.map +1 -0
- package/dist/merge.d.ts +32 -0
- package/dist/merge.d.ts.map +1 -0
- package/dist/merge.js +65 -0
- package/dist/merge.js.map +1 -0
- package/dist/migrations.d.ts +26 -0
- package/dist/migrations.d.ts.map +1 -0
- package/dist/migrations.js +40 -0
- package/dist/migrations.js.map +1 -0
- package/dist/parse.d.ts +7 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +14 -0
- package/dist/parse.js.map +1 -0
- package/dist/paths.d.ts +14 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +37 -0
- package/dist/paths.js.map +1 -0
- package/dist/schema.d.ts +5 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +19 -0
- package/dist/schema.js.map +1 -0
- package/dist/secrets.d.ts +33 -0
- package/dist/secrets.d.ts.map +1 -0
- package/dist/secrets.js +69 -0
- package/dist/secrets.js.map +1 -0
- package/dist/types.d.ts +323 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +20 -0
- package/dist/types.js.map +1 -0
- package/dist/user-config.d.ts +13 -0
- package/dist/user-config.d.ts.map +1 -0
- package/dist/user-config.js +34 -0
- package/dist/user-config.js.map +1 -0
- package/dist/validate.d.ts +36 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +337 -0
- package/dist/validate.js.map +1 -0
- package/package.json +65 -3
- package/schemas/config-v1.json +375 -0
- package/src/chunker-budget.ts +63 -0
- package/src/defaults.ts +207 -0
- package/src/discovery.ts +95 -0
- package/src/env.ts +141 -0
- package/src/hash.ts +71 -0
- package/src/index.ts +51 -0
- package/src/load.ts +346 -0
- package/src/merge.ts +69 -0
- package/src/migrations.ts +64 -0
- package/src/parse.ts +18 -0
- package/src/paths.ts +42 -0
- package/src/schema.ts +23 -0
- package/src/secrets.ts +78 -0
- package/src/types.ts +366 -0
- package/src/user-config.ts +48 -0
- package/src/validate.ts +430 -0
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://untangle.dev/schema/config-v1.json",
|
|
4
|
+
"title": "Untangle Configuration v1",
|
|
5
|
+
"description": "JSON Schema for .untangle.json / .untangle.local.json (spec.md §4.2-4.8, product.md §11, portfolio.md §14.4). This schema is hand-authored for editor tooling (autocompletion, structural hints); it deliberately does NOT encode the 'unknown top-level field warns instead of failing' rule from spec.md §4.8 -- that rule is enforced by @untangle-code/config's own validator, not by schema validation, so additionalProperties:false here is advisory for tooling only.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["schemaVersion"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"$schema": { "type": "string" },
|
|
10
|
+
"schemaVersion": { "const": 1 },
|
|
11
|
+
"workspaceId": { "type": "string", "minLength": 1 },
|
|
12
|
+
"projectId": { "type": "string", "minLength": 1 },
|
|
13
|
+
"repositories": {
|
|
14
|
+
"type": "array",
|
|
15
|
+
"items": { "$ref": "#/$defs/repositoryConfig" }
|
|
16
|
+
},
|
|
17
|
+
"storage": { "$ref": "#/$defs/storageConfig" },
|
|
18
|
+
"qdrant": { "$ref": "#/$defs/qdrantConfig" },
|
|
19
|
+
"embeddings": { "$ref": "#/$defs/embeddingConfig" },
|
|
20
|
+
"index": { "$ref": "#/$defs/indexConfig" },
|
|
21
|
+
"search": { "$ref": "#/$defs/searchConfig" },
|
|
22
|
+
"graph": { "$ref": "#/$defs/graphConfig" },
|
|
23
|
+
"complexity": { "$ref": "#/$defs/complexityConfig" },
|
|
24
|
+
"changes": { "$ref": "#/$defs/changeConfig" },
|
|
25
|
+
"qualityGate": { "$ref": "#/$defs/qualityGateConfig" },
|
|
26
|
+
"contextArtifacts": {
|
|
27
|
+
"type": "array",
|
|
28
|
+
"items": { "$ref": "#/$defs/contextArtifactConfig" }
|
|
29
|
+
},
|
|
30
|
+
"telemetry": { "$ref": "#/$defs/telemetryConfig" },
|
|
31
|
+
"portfolio": { "$ref": "#/$defs/portfolioConfig" }
|
|
32
|
+
},
|
|
33
|
+
"additionalProperties": false,
|
|
34
|
+
"$defs": {
|
|
35
|
+
"repositoryConfig": {
|
|
36
|
+
"type": "object",
|
|
37
|
+
"description": "spec.md §4.3",
|
|
38
|
+
"required": ["id", "path"],
|
|
39
|
+
"properties": {
|
|
40
|
+
"id": { "type": "string", "minLength": 1 },
|
|
41
|
+
"path": { "type": "string", "minLength": 1 },
|
|
42
|
+
"label": { "type": "string" },
|
|
43
|
+
"ref": { "type": "string" },
|
|
44
|
+
"include": { "type": "array", "items": { "type": "string" } },
|
|
45
|
+
"exclude": { "type": "array", "items": { "type": "string" } },
|
|
46
|
+
"packageAliases": { "type": "object", "additionalProperties": { "type": "string" } },
|
|
47
|
+
"metadata": { "type": "object", "additionalProperties": { "type": "string" } }
|
|
48
|
+
},
|
|
49
|
+
"additionalProperties": false
|
|
50
|
+
},
|
|
51
|
+
"storageConfig": {
|
|
52
|
+
"type": "object",
|
|
53
|
+
"description": "Search backend. Defaults to embedded LanceDB unless a legacy qdrant section is explicitly configured. An explicit backend overrides that compatibility default.",
|
|
54
|
+
"properties": {
|
|
55
|
+
"backend": { "enum": ["lancedb", "qdrant"], "default": "lancedb" },
|
|
56
|
+
"path": {
|
|
57
|
+
"type": "string",
|
|
58
|
+
"minLength": 1,
|
|
59
|
+
"description": "Local LanceDB directory, relative to the repository root or absolute; URI schemes and network paths are unsupported.",
|
|
60
|
+
"default": ".untangle/index/lancedb",
|
|
61
|
+
"anyOf": [
|
|
62
|
+
{ "pattern": "^[A-Za-z]:[\\\\/][^\\u0000]*$" },
|
|
63
|
+
{ "pattern": "^(?!\\s*$)(?![A-Za-z][A-Za-z0-9+.-]*:)(?![\\\\/]{2})[^\\u0000]+$" }
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"additionalProperties": false
|
|
68
|
+
},
|
|
69
|
+
"qdrantConfig": {
|
|
70
|
+
"type": "object",
|
|
71
|
+
"description": "spec.md §4.4",
|
|
72
|
+
"required": ["mode"],
|
|
73
|
+
"properties": {
|
|
74
|
+
"mode": { "enum": ["managed", "external"] },
|
|
75
|
+
"url": { "type": "string" },
|
|
76
|
+
"apiKeyEnv": {
|
|
77
|
+
"type": "string",
|
|
78
|
+
"description": "Name of an environment variable; never the key itself (architecture.md §23.2)."
|
|
79
|
+
},
|
|
80
|
+
"collectionPrefix": { "type": "string" },
|
|
81
|
+
"requestTimeoutMs": { "type": "integer", "minimum": 1 },
|
|
82
|
+
"maxRetries": { "type": "integer", "minimum": 0 },
|
|
83
|
+
"upsertMaxPoints": { "type": "integer", "minimum": 1 },
|
|
84
|
+
"upsertBudgetBytes": { "type": "integer", "minimum": 1 }
|
|
85
|
+
},
|
|
86
|
+
"additionalProperties": false
|
|
87
|
+
},
|
|
88
|
+
"embeddingConfig": {
|
|
89
|
+
"type": "object",
|
|
90
|
+
"description": "spec.md §4.5",
|
|
91
|
+
"required": [
|
|
92
|
+
"provider",
|
|
93
|
+
"mode",
|
|
94
|
+
"model",
|
|
95
|
+
"dimensions",
|
|
96
|
+
"contextLength",
|
|
97
|
+
"queryPrefix",
|
|
98
|
+
"documentPrefix",
|
|
99
|
+
"includePath",
|
|
100
|
+
"batchSize",
|
|
101
|
+
"maxConnections",
|
|
102
|
+
"requestTimeoutMs"
|
|
103
|
+
],
|
|
104
|
+
"properties": {
|
|
105
|
+
"provider": { "const": "ollama" },
|
|
106
|
+
"mode": { "enum": ["auto", "managed", "external"] },
|
|
107
|
+
"url": { "type": "string" },
|
|
108
|
+
"apiKeyEnv": {
|
|
109
|
+
"type": "string",
|
|
110
|
+
"description": "Name of an environment variable; never the key itself (architecture.md §23.2)."
|
|
111
|
+
},
|
|
112
|
+
"model": { "type": "string", "minLength": 1 },
|
|
113
|
+
"dimensions": { "type": "integer", "minimum": 1 },
|
|
114
|
+
"contextLength": { "type": "integer", "minimum": 1 },
|
|
115
|
+
"queryPrefix": { "type": "string" },
|
|
116
|
+
"documentPrefix": { "type": "string" },
|
|
117
|
+
"includePath": { "type": "boolean" },
|
|
118
|
+
"batchSize": { "type": "integer", "minimum": 1 },
|
|
119
|
+
"maxConnections": { "type": "integer", "minimum": 1 },
|
|
120
|
+
"requestTimeoutMs": { "type": "integer", "minimum": 1 }
|
|
121
|
+
},
|
|
122
|
+
"additionalProperties": false
|
|
123
|
+
},
|
|
124
|
+
"indexConfig": {
|
|
125
|
+
"type": "object",
|
|
126
|
+
"description": "spec.md §4.6",
|
|
127
|
+
"properties": {
|
|
128
|
+
"watch": { "type": "boolean" },
|
|
129
|
+
"reconcileIntervalMinutes": { "type": "number", "minimum": 0 },
|
|
130
|
+
"maxFileSizeMb": { "type": "number", "minimum": 0 },
|
|
131
|
+
"maxGraphFileSizeMb": { "type": "number", "minimum": 0 },
|
|
132
|
+
"scanConcurrency": { "type": "integer", "minimum": 1 },
|
|
133
|
+
"embeddingConcurrency": { "type": "integer", "minimum": 1 },
|
|
134
|
+
"filesPerCheckpoint": { "type": "integer", "minimum": 1 },
|
|
135
|
+
"targetChunkTokens": { "type": "integer", "minimum": 1 },
|
|
136
|
+
"maxChunkTokens": { "type": "integer", "minimum": 1 },
|
|
137
|
+
"fallbackOverlapTokens": { "type": "integer", "minimum": 0 },
|
|
138
|
+
"includeDotFiles": { "type": "boolean" },
|
|
139
|
+
"indexExtensionless": { "type": "boolean" },
|
|
140
|
+
"extraExtensions": { "type": "array", "items": { "type": "string" } },
|
|
141
|
+
"extensionLanguageMap": { "type": "object", "additionalProperties": { "type": "string" } }
|
|
142
|
+
},
|
|
143
|
+
"additionalProperties": false
|
|
144
|
+
},
|
|
145
|
+
"searchConfig": {
|
|
146
|
+
"type": "object",
|
|
147
|
+
"description": "Untangle decision: spec.md §13 names no SearchConfig shape.",
|
|
148
|
+
"properties": {
|
|
149
|
+
"defaultLimit": { "type": "integer", "minimum": 1 },
|
|
150
|
+
"defaultCandidateLimit": { "type": "integer", "minimum": 1 },
|
|
151
|
+
"maxCandidateLimit": { "type": "integer", "minimum": 1 },
|
|
152
|
+
"diversifyByDefault": { "type": "boolean" },
|
|
153
|
+
"minScoreDefault": { "type": "number" },
|
|
154
|
+
"relevancePolicies": {
|
|
155
|
+
"type": "object",
|
|
156
|
+
"description": "Calibrated absence decisions keyed by the exact embedding profile id and additionally bound to one workspace and collection.",
|
|
157
|
+
"propertyNames": { "type": "string", "minLength": 1 },
|
|
158
|
+
"additionalProperties": { "$ref": "#/$defs/searchRelevancePolicyBinding" }
|
|
159
|
+
},
|
|
160
|
+
"boostWeights": {
|
|
161
|
+
"type": "object",
|
|
162
|
+
"properties": {
|
|
163
|
+
"exactSymbol": { "type": "number" },
|
|
164
|
+
"exactPath": { "type": "number" },
|
|
165
|
+
"repoPriority": { "type": "number" },
|
|
166
|
+
"graphProximity": { "type": "number" },
|
|
167
|
+
"recency": { "type": "number" },
|
|
168
|
+
"duplicatePenalty": { "type": "number" }
|
|
169
|
+
},
|
|
170
|
+
"additionalProperties": false
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
"additionalProperties": false
|
|
174
|
+
},
|
|
175
|
+
"searchRelevancePolicyBinding": {
|
|
176
|
+
"type": "object",
|
|
177
|
+
"required": ["workspaceId", "collection", "policy"],
|
|
178
|
+
"properties": {
|
|
179
|
+
"workspaceId": { "type": "string", "minLength": 1 },
|
|
180
|
+
"collection": { "type": "string", "minLength": 1 },
|
|
181
|
+
"policy": { "$ref": "#/$defs/searchRelevancePolicy" }
|
|
182
|
+
},
|
|
183
|
+
"additionalProperties": false
|
|
184
|
+
},
|
|
185
|
+
"searchRelevancePolicy": {
|
|
186
|
+
"type": "object",
|
|
187
|
+
"required": [
|
|
188
|
+
"calibrationId",
|
|
189
|
+
"minimumDenseScore",
|
|
190
|
+
"minimumDenseSpread",
|
|
191
|
+
"denseReferenceRank",
|
|
192
|
+
"minimumCandidateIdfCoverage"
|
|
193
|
+
],
|
|
194
|
+
"properties": {
|
|
195
|
+
"calibrationId": { "type": "string", "minLength": 1 },
|
|
196
|
+
"minimumDenseScore": { "type": "number", "minimum": -1, "maximum": 1 },
|
|
197
|
+
"minimumDenseSpread": { "type": "number", "minimum": 0, "maximum": 2 },
|
|
198
|
+
"denseReferenceRank": { "type": "integer", "minimum": 2 },
|
|
199
|
+
"minimumCandidateIdfCoverage": { "type": "number", "minimum": 0, "maximum": 1 }
|
|
200
|
+
},
|
|
201
|
+
"additionalProperties": false
|
|
202
|
+
},
|
|
203
|
+
"graphConfig": {
|
|
204
|
+
"type": "object",
|
|
205
|
+
"description": "Untangle decision, values anchored on architecture.md §17.4 traversal limits.",
|
|
206
|
+
"properties": {
|
|
207
|
+
"enabled": { "type": "boolean" },
|
|
208
|
+
"maxTraversalDepth": { "type": "integer", "minimum": 1 },
|
|
209
|
+
"maxTraversalNodes": { "type": "integer", "minimum": 1 },
|
|
210
|
+
"maxTraversalEdges": { "type": "integer", "minimum": 1 },
|
|
211
|
+
"maxTraversalWallTimeMs": { "type": "integer", "minimum": 1 },
|
|
212
|
+
"includeDynamicImports": { "type": "boolean" }
|
|
213
|
+
},
|
|
214
|
+
"additionalProperties": false
|
|
215
|
+
},
|
|
216
|
+
"complexityConfig": {
|
|
217
|
+
"type": "object",
|
|
218
|
+
"description": "Untangle decision; product.md §11 example anchors 'enabled'/'cognitiveAlgorithm'.",
|
|
219
|
+
"properties": {
|
|
220
|
+
"enabled": { "type": "boolean" },
|
|
221
|
+
"cognitiveAlgorithm": { "type": "string" },
|
|
222
|
+
"cyclomaticVariant": { "enum": ["classic", "extended", "both"] },
|
|
223
|
+
"maintainabilityIndexEnabled": { "type": "boolean" }
|
|
224
|
+
},
|
|
225
|
+
"additionalProperties": false
|
|
226
|
+
},
|
|
227
|
+
"changeConfig": {
|
|
228
|
+
"type": "object",
|
|
229
|
+
"description": "Untangle decision; weight defaults from spec.md §17.6.",
|
|
230
|
+
"properties": {
|
|
231
|
+
"enabled": { "type": "boolean" },
|
|
232
|
+
"riskWeights": {
|
|
233
|
+
"type": "object",
|
|
234
|
+
"properties": {
|
|
235
|
+
"churn": { "type": "number" },
|
|
236
|
+
"positiveCognitiveDelta": { "type": "number" },
|
|
237
|
+
"positiveCyclomaticDelta": { "type": "number" },
|
|
238
|
+
"blastRadius": { "type": "number" },
|
|
239
|
+
"graphCentrality": { "type": "number" },
|
|
240
|
+
"semanticChange": { "type": "number" },
|
|
241
|
+
"testDistance": { "type": "number" }
|
|
242
|
+
},
|
|
243
|
+
"additionalProperties": false
|
|
244
|
+
},
|
|
245
|
+
"symbolMatching": {
|
|
246
|
+
"type": "object",
|
|
247
|
+
"properties": {
|
|
248
|
+
"tokenSimilarityMin": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
249
|
+
"enableEmbeddingSimilarity": { "type": "boolean" }
|
|
250
|
+
},
|
|
251
|
+
"additionalProperties": false
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
"additionalProperties": false
|
|
255
|
+
},
|
|
256
|
+
"qualityGateConfig": {
|
|
257
|
+
"type": "object",
|
|
258
|
+
"description": "spec.md §4.7",
|
|
259
|
+
"required": ["mode", "newCyclesAllowed", "minimumParseQuality", "ignoreExistingViolations"],
|
|
260
|
+
"properties": {
|
|
261
|
+
"mode": { "enum": ["off", "warn", "fail"] },
|
|
262
|
+
"newCyclesAllowed": { "type": "integer", "minimum": 0 },
|
|
263
|
+
"cognitivePerSymbolMax": { "type": "number" },
|
|
264
|
+
"cognitiveDeltaPerSymbolMax": { "type": "number" },
|
|
265
|
+
"cyclomaticPerSymbolMax": { "type": "number" },
|
|
266
|
+
"cyclomaticDeltaPerSymbolMax": { "type": "number" },
|
|
267
|
+
"maxNestingPerSymbolMax": { "type": "number" },
|
|
268
|
+
"maintainabilityIndexMin": { "type": "number" },
|
|
269
|
+
"riskScoreMax": { "type": "number" },
|
|
270
|
+
"minimumParseQuality": { "enum": ["failed", "partial", "complete"] },
|
|
271
|
+
"ignoreExistingViolations": { "type": "boolean" },
|
|
272
|
+
"include": { "type": "array", "items": { "type": "string" } },
|
|
273
|
+
"exclude": { "type": "array", "items": { "type": "string" } }
|
|
274
|
+
},
|
|
275
|
+
"additionalProperties": false
|
|
276
|
+
},
|
|
277
|
+
"contextArtifactConfig": {
|
|
278
|
+
"type": "object",
|
|
279
|
+
"description": "spec.md §19.1-19.2",
|
|
280
|
+
"required": ["name", "path", "description"],
|
|
281
|
+
"properties": {
|
|
282
|
+
"name": { "type": "string", "minLength": 1 },
|
|
283
|
+
"path": { "type": "string", "minLength": 1 },
|
|
284
|
+
"description": { "type": "string" },
|
|
285
|
+
"type": {
|
|
286
|
+
"enum": [
|
|
287
|
+
"auto",
|
|
288
|
+
"sql",
|
|
289
|
+
"openapi",
|
|
290
|
+
"asyncapi",
|
|
291
|
+
"protobuf",
|
|
292
|
+
"markdown",
|
|
293
|
+
"terraform",
|
|
294
|
+
"kubernetes",
|
|
295
|
+
"text"
|
|
296
|
+
]
|
|
297
|
+
},
|
|
298
|
+
"include": { "type": "array", "items": { "type": "string" } },
|
|
299
|
+
"exclude": { "type": "array", "items": { "type": "string" } }
|
|
300
|
+
},
|
|
301
|
+
"additionalProperties": false
|
|
302
|
+
},
|
|
303
|
+
"telemetryConfig": {
|
|
304
|
+
"type": "object",
|
|
305
|
+
"description": "spec.md §24: telemetry MUST default to off.",
|
|
306
|
+
"properties": {
|
|
307
|
+
"enabled": { "type": "boolean" },
|
|
308
|
+
"logLevel": { "enum": ["error", "warn", "info", "debug", "trace"] },
|
|
309
|
+
"metricsExport": { "enum": ["none", "prometheus"] }
|
|
310
|
+
},
|
|
311
|
+
"additionalProperties": false
|
|
312
|
+
},
|
|
313
|
+
"portfolioConfig": {
|
|
314
|
+
"type": "object",
|
|
315
|
+
"description": "portfolio.md §14.4 (normative shape)",
|
|
316
|
+
"properties": {
|
|
317
|
+
"enabled": { "type": "boolean" },
|
|
318
|
+
"includeTransitive": { "type": "boolean" },
|
|
319
|
+
"conventionMinRepos": { "type": "integer", "minimum": 0 },
|
|
320
|
+
"conventions": {
|
|
321
|
+
"type": "object",
|
|
322
|
+
"properties": {
|
|
323
|
+
"pinned": { "type": "array", "items": { "type": "string" } },
|
|
324
|
+
"suppressed": { "type": "array", "items": { "type": "string" } }
|
|
325
|
+
},
|
|
326
|
+
"additionalProperties": false
|
|
327
|
+
},
|
|
328
|
+
"radar": {
|
|
329
|
+
"type": "object",
|
|
330
|
+
"properties": {
|
|
331
|
+
"adoptShareMin": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
332
|
+
"maintainShareMin": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
333
|
+
"retireAfterDays": { "type": "integer", "minimum": 0 }
|
|
334
|
+
},
|
|
335
|
+
"additionalProperties": false
|
|
336
|
+
},
|
|
337
|
+
"blueprint": {
|
|
338
|
+
"type": "object",
|
|
339
|
+
"properties": {
|
|
340
|
+
"weights": {
|
|
341
|
+
"type": "object",
|
|
342
|
+
"description": "MUST sum to 1.0 (±0.001) -- portfolio.md §14.4.",
|
|
343
|
+
"properties": {
|
|
344
|
+
"adoption": { "type": "number" },
|
|
345
|
+
"recency": { "type": "number" },
|
|
346
|
+
"health": { "type": "number" },
|
|
347
|
+
"versionConsistency": { "type": "number" }
|
|
348
|
+
},
|
|
349
|
+
"additionalProperties": false
|
|
350
|
+
}
|
|
351
|
+
},
|
|
352
|
+
"additionalProperties": false
|
|
353
|
+
},
|
|
354
|
+
"enrichment": { "$ref": "#/$defs/portfolioEnrichmentConfig" }
|
|
355
|
+
},
|
|
356
|
+
"additionalProperties": false
|
|
357
|
+
},
|
|
358
|
+
"portfolioEnrichmentConfig": {
|
|
359
|
+
"type": "object",
|
|
360
|
+
"description": "portfolio.md §13. Default fully disabled.",
|
|
361
|
+
"required": ["enabled", "registries", "cacheTtlHours", "timeoutMs"],
|
|
362
|
+
"properties": {
|
|
363
|
+
"enabled": { "type": "boolean" },
|
|
364
|
+
"registries": {
|
|
365
|
+
"type": "array",
|
|
366
|
+
"items": { "enum": ["npm", "pypi", "crates", "maven", "nuget", "go", "composer"] }
|
|
367
|
+
},
|
|
368
|
+
"registryUrls": { "type": "object", "additionalProperties": { "type": "string" } },
|
|
369
|
+
"cacheTtlHours": { "type": "number", "minimum": 0 },
|
|
370
|
+
"timeoutMs": { "type": "integer", "minimum": 1 }
|
|
371
|
+
},
|
|
372
|
+
"additionalProperties": false
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chunk-token budget wiring: `IndexConfig` (spec.md §4.6) →
|
|
3
|
+
* `@untangle-code/chunker`'s `ChunkerConfigInput.maxTokensPerChunk`.
|
|
4
|
+
*
|
|
5
|
+
* spec.md §4.6 defines TWO index-level chunk-size knobs —
|
|
6
|
+
* `targetChunkTokens` (a soft aim) and `maxChunkTokens` (a hard ceiling) —
|
|
7
|
+
* with their product defaults (900 / 1500) fixed exactly once, in this
|
|
8
|
+
* package's `defaults.ts` (`DEFAULT_INDEX_CONFIG`). That is the single
|
|
9
|
+
* source of truth this file wires onward.
|
|
10
|
+
*
|
|
11
|
+
* `@untangle-code/chunker` currently exposes exactly ONE budget knob,
|
|
12
|
+
* `ChunkerConfigInput.maxTokensPerChunk`, and treats it everywhere as a hard
|
|
13
|
+
* "must not exceed" ceiling (every comparison in chunker's `split.ts` and
|
|
14
|
+
* `line-fallback-strategy.ts` is `<=`). The correct mapping is therefore
|
|
15
|
+
* `maxChunkTokens → maxTokensPerChunk`. `targetChunkTokens` has no
|
|
16
|
+
* chunker-side counterpart today — the chunker does not currently support
|
|
17
|
+
* aiming below its hard ceiling — and is deliberately NOT passed here;
|
|
18
|
+
* smuggling it in as `maxTokensPerChunk` instead would silently turn a soft
|
|
19
|
+
* aim into the hard ceiling the chunker actually enforces, which is a
|
|
20
|
+
* different (smaller) budget than spec.md §4.6 configures.
|
|
21
|
+
*
|
|
22
|
+
* `@untangle-code/config` deliberately does NOT take a runtime dependency on
|
|
23
|
+
* `@untangle-code/chunker` for this: config sits below chunker in the
|
|
24
|
+
* dependency graph (chunker already depends on domain; depending on chunker
|
|
25
|
+
* from here would invert that layering for the sake of one field mapping),
|
|
26
|
+
* and chunker is maintained independently of this package. `deriveChunkerBudget`
|
|
27
|
+
* therefore returns a plain object structurally compatible with
|
|
28
|
+
* `ChunkerConfigInput` (verified in `chunker-budget.test.ts` against the
|
|
29
|
+
* fields spec.md and the chunker README actually document) rather than
|
|
30
|
+
* importing its type.
|
|
31
|
+
*
|
|
32
|
+
* Whatever code builds the indexer (constructing `ChunkerConfigInput` to
|
|
33
|
+
* pass to `@untangle-code/chunker`'s `resolveChunkerConfig`/`chunkFile`) MUST
|
|
34
|
+
* spread this function's result into that input — e.g.
|
|
35
|
+
* `resolveChunkerConfig({ ...deriveChunkerBudget(effectiveConfig.index), preparedText })`
|
|
36
|
+
* — rather than reading `index.maxChunkTokens` directly or (worse) relying
|
|
37
|
+
* on the chunker's own independent default. That is the one piece of wiring
|
|
38
|
+
* this fix cannot complete by itself: no indexer package exists in this
|
|
39
|
+
* repository yet to receive it (see this package's `package.json`
|
|
40
|
+
* `dependencies`, and `packages/`'s directory listing) — but every future
|
|
41
|
+
* caller now has exactly one function to call instead of a field name to
|
|
42
|
+
* remember, which is what keeps a changed config value from silently
|
|
43
|
+
* failing to reach the chunker.
|
|
44
|
+
*/
|
|
45
|
+
import type { IndexConfig } from "./types.js";
|
|
46
|
+
|
|
47
|
+
/** Structurally assignable to `@untangle-code/chunker`'s `ChunkerConfigInput` — see file doc comment. */
|
|
48
|
+
export interface ChunkerBudgetInput {
|
|
49
|
+
maxTokensPerChunk: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Derives the chunker's token-budget input from the effective `IndexConfig`
|
|
54
|
+
* (spec.md §4.6). This is the ONLY function in the codebase permitted to
|
|
55
|
+
* decide which `IndexConfig` field feeds
|
|
56
|
+
* `ChunkerConfigInput.maxTokensPerChunk` — see file doc comment for why it
|
|
57
|
+
* is `maxChunkTokens`, not `targetChunkTokens`.
|
|
58
|
+
*/
|
|
59
|
+
export function deriveChunkerBudget(
|
|
60
|
+
index: Pick<IndexConfig, "maxChunkTokens">,
|
|
61
|
+
): ChunkerBudgetInput {
|
|
62
|
+
return { maxTokensPerChunk: index.maxChunkTokens };
|
|
63
|
+
}
|
package/src/defaults.ts
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Product defaults (spec.md §4.5 "Defaultprofil für MVP"; product.md §11).
|
|
3
|
+
*
|
|
4
|
+
* These are layer 6 (lowest priority) of spec.md §4.1's six-level layering.
|
|
5
|
+
* Every field an `EffectiveUntangleConfigV1` guarantees present is defaulted
|
|
6
|
+
* here.
|
|
7
|
+
*/
|
|
8
|
+
import { COGNITIVE_ALGORITHM_ID } from "@untangle-code/domain";
|
|
9
|
+
|
|
10
|
+
import type {
|
|
11
|
+
ChangeConfig,
|
|
12
|
+
ComplexityConfig,
|
|
13
|
+
EmbeddingConfig,
|
|
14
|
+
GraphConfig,
|
|
15
|
+
IndexConfig,
|
|
16
|
+
PortfolioConfig,
|
|
17
|
+
QdrantConfig,
|
|
18
|
+
QualityGateConfig,
|
|
19
|
+
RawConfigLayer,
|
|
20
|
+
SearchConfig,
|
|
21
|
+
StorageConfig,
|
|
22
|
+
TelemetryConfig,
|
|
23
|
+
} from "./types.js";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Embedding profile fields that are NOT part of `EmbeddingConfig` (spec.md
|
|
27
|
+
* §4.5 lists exactly ten fields, none of them `normalization` or
|
|
28
|
+
* `preparedTextVersion`) but ARE required inputs to
|
|
29
|
+
* `buildEmbeddingProfileId` (spec.md §5.7). Untangle decision: default
|
|
30
|
+
* normalization to "none" (no vector post-processing) and mint an explicit
|
|
31
|
+
* prepared-text format version so a future change to how document text is
|
|
32
|
+
* assembled can roll `embedding_profile_id` forward deliberately.
|
|
33
|
+
*/
|
|
34
|
+
export const DEFAULT_EMBEDDING_NORMALIZATION = "none" as const;
|
|
35
|
+
export const PREPARED_TEXT_VERSION = "untangle-prepared-text-v1" as const;
|
|
36
|
+
|
|
37
|
+
/** spec.md §4.5 "Defaultprofil für MVP" — Ollama, nomic-embed-text, 768 dims. */
|
|
38
|
+
export const DEFAULT_EMBEDDING_CONFIG: EmbeddingConfig = {
|
|
39
|
+
provider: "ollama",
|
|
40
|
+
mode: "auto",
|
|
41
|
+
model: "nomic-embed-text",
|
|
42
|
+
dimensions: 768,
|
|
43
|
+
contextLength: 2048,
|
|
44
|
+
queryPrefix: "search_query: ",
|
|
45
|
+
documentPrefix: "search_document: ",
|
|
46
|
+
includePath: true,
|
|
47
|
+
batchSize: 32,
|
|
48
|
+
maxConnections: 4,
|
|
49
|
+
requestTimeoutMs: 120000,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Qdrant defaults. spec.md §4.4 defines the shape but not default values;
|
|
54
|
+
* `managed` mode with no explicit `url` matches product.md §4.1's
|
|
55
|
+
* zero-config narrative (the CLI starts a managed container and fills `url`
|
|
56
|
+
* in from that at runtime — this package only supplies the mode default).
|
|
57
|
+
*/
|
|
58
|
+
export const DEFAULT_QDRANT_CONFIG: QdrantConfig = {
|
|
59
|
+
mode: "managed",
|
|
60
|
+
collectionPrefix: "untangle_",
|
|
61
|
+
requestTimeoutMs: 30000,
|
|
62
|
+
maxRetries: 3,
|
|
63
|
+
upsertMaxPoints: 256,
|
|
64
|
+
upsertBudgetBytes: 4 * 1024 * 1024,
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/** Embedded search for new projects; explicit legacy Qdrant layers retain their backend. */
|
|
68
|
+
export const DEFAULT_STORAGE_CONFIG: StorageConfig = {
|
|
69
|
+
backend: "lancedb",
|
|
70
|
+
path: ".untangle/index/lancedb",
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/** spec.md §4.6; numeric defaults are an Untangle decision, chosen conservatively. */
|
|
74
|
+
export const DEFAULT_INDEX_CONFIG: IndexConfig = {
|
|
75
|
+
watch: true,
|
|
76
|
+
reconcileIntervalMinutes: 30,
|
|
77
|
+
maxFileSizeMb: 5,
|
|
78
|
+
maxGraphFileSizeMb: 20,
|
|
79
|
+
scanConcurrency: 8,
|
|
80
|
+
embeddingConcurrency: 4,
|
|
81
|
+
filesPerCheckpoint: 200,
|
|
82
|
+
targetChunkTokens: 900,
|
|
83
|
+
maxChunkTokens: 1500,
|
|
84
|
+
fallbackOverlapTokens: 100,
|
|
85
|
+
includeDotFiles: false,
|
|
86
|
+
indexExtensionless: false,
|
|
87
|
+
extraExtensions: [],
|
|
88
|
+
extensionLanguageMap: {},
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/** Untangle decision (see `types.ts` `SearchConfig` doc comment). */
|
|
92
|
+
export const DEFAULT_SEARCH_CONFIG: SearchConfig = {
|
|
93
|
+
defaultLimit: 10,
|
|
94
|
+
defaultCandidateLimit: 50,
|
|
95
|
+
maxCandidateLimit: 200,
|
|
96
|
+
diversifyByDefault: false,
|
|
97
|
+
boostWeights: {
|
|
98
|
+
exactSymbol: 0.15,
|
|
99
|
+
exactPath: 0.1,
|
|
100
|
+
repoPriority: 0.05,
|
|
101
|
+
graphProximity: 0.1,
|
|
102
|
+
recency: 0.05,
|
|
103
|
+
duplicatePenalty: 0.2,
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
/** Untangle decision, values taken from architecture.md §17.4's per-query limits. */
|
|
108
|
+
export const DEFAULT_GRAPH_CONFIG: GraphConfig = {
|
|
109
|
+
enabled: true,
|
|
110
|
+
maxTraversalDepth: 20,
|
|
111
|
+
maxTraversalNodes: 2000,
|
|
112
|
+
maxTraversalEdges: 4000,
|
|
113
|
+
maxTraversalWallTimeMs: 5000,
|
|
114
|
+
includeDynamicImports: true,
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/** Untangle decision (see `types.ts` `ComplexityConfig` doc comment). */
|
|
118
|
+
export const DEFAULT_COMPLEXITY_CONFIG: ComplexityConfig = {
|
|
119
|
+
enabled: true,
|
|
120
|
+
cognitiveAlgorithm: COGNITIVE_ALGORITHM_ID,
|
|
121
|
+
cyclomaticVariant: "both",
|
|
122
|
+
maintainabilityIndexEnabled: true,
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/** spec.md §17.6 default risk score weights. */
|
|
126
|
+
export const DEFAULT_CHANGE_CONFIG: ChangeConfig = {
|
|
127
|
+
enabled: true,
|
|
128
|
+
riskWeights: {
|
|
129
|
+
churn: 0.25,
|
|
130
|
+
positiveCognitiveDelta: 0.2,
|
|
131
|
+
positiveCyclomaticDelta: 0.15,
|
|
132
|
+
blastRadius: 0.15,
|
|
133
|
+
graphCentrality: 0.1,
|
|
134
|
+
semanticChange: 0.1,
|
|
135
|
+
testDistance: 0.05,
|
|
136
|
+
},
|
|
137
|
+
symbolMatching: {
|
|
138
|
+
tokenSimilarityMin: 0.6,
|
|
139
|
+
enableEmbeddingSimilarity: true,
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
/** spec.md §4.7 shape; MVP defaults chosen deliberately permissive (warn, not fail). */
|
|
144
|
+
export const DEFAULT_QUALITY_GATE_CONFIG: QualityGateConfig = {
|
|
145
|
+
mode: "warn",
|
|
146
|
+
newCyclesAllowed: 0,
|
|
147
|
+
minimumParseQuality: "partial",
|
|
148
|
+
ignoreExistingViolations: true,
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
/** spec.md §24: "Telemetrie MUSS standardmäßig aus sein." */
|
|
152
|
+
export const DEFAULT_TELEMETRY_CONFIG: TelemetryConfig = {
|
|
153
|
+
enabled: false,
|
|
154
|
+
logLevel: "info",
|
|
155
|
+
metricsExport: "none",
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/** portfolio.md §14.4 defaults, spelled out explicitly. */
|
|
159
|
+
export const DEFAULT_PORTFOLIO_CONFIG: PortfolioConfig = {
|
|
160
|
+
enabled: true,
|
|
161
|
+
includeTransitive: false,
|
|
162
|
+
conventionMinRepos: 2,
|
|
163
|
+
radar: {
|
|
164
|
+
adoptShareMin: 0.5,
|
|
165
|
+
maintainShareMin: 0.2,
|
|
166
|
+
retireAfterDays: 540,
|
|
167
|
+
},
|
|
168
|
+
blueprint: {
|
|
169
|
+
weights: {
|
|
170
|
+
adoption: 0.4,
|
|
171
|
+
recency: 0.2,
|
|
172
|
+
health: 0.25,
|
|
173
|
+
versionConsistency: 0.15,
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
enrichment: {
|
|
177
|
+
enabled: false,
|
|
178
|
+
registries: [],
|
|
179
|
+
cacheTtlHours: 168,
|
|
180
|
+
timeoutMs: 10000,
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
/** Current config schema version this package produces and validates against. */
|
|
185
|
+
export const CURRENT_SCHEMA_VERSION = 1 as const;
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* The complete product-default layer (spec.md §4.1 layer 6, lowest
|
|
189
|
+
* priority). Every optional sub-config `EffectiveUntangleConfigV1`
|
|
190
|
+
* guarantees present is defaulted here; `repositories` and
|
|
191
|
+
* `contextArtifacts` are deliberately absent (spec.md §4.3: no universal
|
|
192
|
+
* default repository set exists).
|
|
193
|
+
*/
|
|
194
|
+
export const PRODUCT_DEFAULT_CONFIG: RawConfigLayer = {
|
|
195
|
+
schemaVersion: CURRENT_SCHEMA_VERSION,
|
|
196
|
+
storage: DEFAULT_STORAGE_CONFIG,
|
|
197
|
+
qdrant: DEFAULT_QDRANT_CONFIG,
|
|
198
|
+
embeddings: DEFAULT_EMBEDDING_CONFIG,
|
|
199
|
+
index: DEFAULT_INDEX_CONFIG,
|
|
200
|
+
search: DEFAULT_SEARCH_CONFIG,
|
|
201
|
+
graph: DEFAULT_GRAPH_CONFIG,
|
|
202
|
+
complexity: DEFAULT_COMPLEXITY_CONFIG,
|
|
203
|
+
changes: DEFAULT_CHANGE_CONFIG,
|
|
204
|
+
qualityGate: DEFAULT_QUALITY_GATE_CONFIG,
|
|
205
|
+
telemetry: DEFAULT_TELEMETRY_CONFIG,
|
|
206
|
+
portfolio: DEFAULT_PORTFOLIO_CONFIG,
|
|
207
|
+
};
|