@fenglimg/fabric-shared 2.2.0-rc.4 → 2.2.0-rc.8
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/dist/chunk-2GLIAZ5M.js +251 -0
- package/dist/{chunk-355LUDLW.js → chunk-5AKCRBKJ.js} +474 -418
- package/dist/{chunk-KUYCTRFI.js → chunk-B2N3I7UX.js} +390 -532
- package/dist/chunk-BDJQIOQO.js +206 -0
- package/dist/{chunk-4N6DMOOW.js → chunk-C7WZPYZE.js} +2 -1
- package/dist/{chunk-VDSM73PK.js → chunk-O6GIHZF3.js} +6 -0
- package/dist/errors/index.d.ts +6 -1
- package/dist/errors/index.js +5 -3
- package/dist/i18n/index.d.ts +29 -23
- package/dist/i18n/index.js +7 -3
- package/dist/{index-BqA89S9q.d.ts → index-SrmixArL.d.ts} +83 -28
- package/dist/index.d.ts +490 -549
- package/dist/index.js +1277 -1026
- package/dist/node/atomic-write.js +1 -1
- package/dist/node/mcp-payload-guard.js +1 -1
- package/dist/node.d.ts +10 -1
- package/dist/node.js +32 -1
- package/dist/schemas/api-contracts.d.ts +163 -113
- package/dist/schemas/api-contracts.js +3 -3
- package/dist/templates/bootstrap-canonical.d.ts +50 -23
- package/dist/templates/bootstrap-canonical.js +12 -9
- package/dist/types/index.d.ts +1 -1
- package/dist/types-qg4xXVuT.d.ts +8 -0
- package/package.json +3 -2
- package/dist/chunk-AFT7DB4P.js +0 -103
package/dist/index.js
CHANGED
|
@@ -1,26 +1,16 @@
|
|
|
1
|
-
import
|
|
2
|
-
BOOTSTRAP_CANONICAL,
|
|
3
|
-
BOOTSTRAP_MARKER_BEGIN,
|
|
4
|
-
BOOTSTRAP_MARKER_END,
|
|
5
|
-
BOOTSTRAP_REGEX,
|
|
6
|
-
LEGACY_KB_MARKER_BEGIN,
|
|
7
|
-
LEGACY_KB_MARKER_END,
|
|
8
|
-
LEGACY_KB_REGEX
|
|
9
|
-
} from "./chunk-AFT7DB4P.js";
|
|
1
|
+
import "./chunk-LXNCAKJZ.js";
|
|
10
2
|
import {
|
|
11
3
|
PROTECTED_TOKENS,
|
|
12
4
|
createTranslator,
|
|
13
5
|
defaultMessages,
|
|
14
|
-
detectNodeLocale,
|
|
15
6
|
enMessages,
|
|
16
|
-
normalizeLocale,
|
|
17
7
|
resolveFabricLocale,
|
|
18
8
|
zhCNMessages
|
|
19
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-B2N3I7UX.js";
|
|
20
10
|
import {
|
|
21
11
|
atomicWriteJson,
|
|
22
12
|
withFileLock
|
|
23
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-C7WZPYZE.js";
|
|
24
14
|
import {
|
|
25
15
|
FabExtractKnowledgeInputSchema,
|
|
26
16
|
FabExtractKnowledgeInputShape,
|
|
@@ -30,14 +20,17 @@ import {
|
|
|
30
20
|
FabReviewOutputSchema,
|
|
31
21
|
FabReviewOutputShape,
|
|
32
22
|
KNOWLEDGE_TYPE_CODES,
|
|
23
|
+
KNOWN_SCOPE_PREFIXES,
|
|
33
24
|
KnowledgeEntryFrontmatterSchema,
|
|
34
25
|
KnowledgeTypeSchema,
|
|
35
26
|
LayerSchema,
|
|
36
27
|
MaturitySchema,
|
|
37
28
|
ONBOARD_SLOT_NAMES,
|
|
38
29
|
ONBOARD_SLOT_TOTAL,
|
|
39
|
-
|
|
30
|
+
PERSONAL_SCOPE,
|
|
31
|
+
PROPOSED_REASON_DESCRIPTIONS_BY_LOCALE,
|
|
40
32
|
ProposedReasonSchema,
|
|
33
|
+
SCOPE_COORDINATE_PATTERN,
|
|
41
34
|
StableIdSchema,
|
|
42
35
|
annotateIntentRequestSchema,
|
|
43
36
|
archiveScanAnnotations,
|
|
@@ -46,12 +39,14 @@ import {
|
|
|
46
39
|
citeContractMetricsSchema,
|
|
47
40
|
citeCoverageReportSchema,
|
|
48
41
|
citeLayerTypeBreakdownSchema,
|
|
42
|
+
entryScopeMetadataSchema,
|
|
49
43
|
fabExtractKnowledgeAnnotations,
|
|
50
44
|
fabReviewAnnotations,
|
|
51
45
|
formatKnowledgeId,
|
|
52
46
|
historyStateQuerySchema,
|
|
53
47
|
humanLockApproveRequestSchema,
|
|
54
48
|
humanLockFileParamsSchema,
|
|
49
|
+
isPersonalScope,
|
|
55
50
|
knowledgeSectionsAnnotations,
|
|
56
51
|
knowledgeSectionsInputSchema,
|
|
57
52
|
knowledgeSectionsOutputSchema,
|
|
@@ -67,9 +62,55 @@ import {
|
|
|
67
62
|
recallAnnotations,
|
|
68
63
|
recallInputSchema,
|
|
69
64
|
recallOutputSchema,
|
|
65
|
+
scopeCoordinateSchema,
|
|
66
|
+
scopeRoot,
|
|
70
67
|
structuredWarningSchema
|
|
71
|
-
} from "./chunk-
|
|
72
|
-
import
|
|
68
|
+
} from "./chunk-5AKCRBKJ.js";
|
|
69
|
+
import {
|
|
70
|
+
BOOTSTRAP_CANONICAL_BY_LOCALE,
|
|
71
|
+
BOOTSTRAP_CANONICAL_EN,
|
|
72
|
+
BOOTSTRAP_CANONICAL_ZH,
|
|
73
|
+
BOOTSTRAP_MARKER_BEGIN,
|
|
74
|
+
BOOTSTRAP_MARKER_END,
|
|
75
|
+
BOOTSTRAP_REGEX,
|
|
76
|
+
matchBootstrapCanonicalLocale,
|
|
77
|
+
resolveBootstrapCanonical
|
|
78
|
+
} from "./chunk-BDJQIOQO.js";
|
|
79
|
+
import {
|
|
80
|
+
GLOBAL_BINDINGS_DIR,
|
|
81
|
+
GLOBAL_STATE_DIR,
|
|
82
|
+
PERSONAL_STORE_SENTINEL,
|
|
83
|
+
STORES_ROOT_DIR,
|
|
84
|
+
STORE_ALIAS_PATTERN,
|
|
85
|
+
STORE_KNOWLEDGE_TYPE_DIRS,
|
|
86
|
+
STORE_LAYOUT,
|
|
87
|
+
STORE_MOUNT_GROUPS,
|
|
88
|
+
STORE_MOUNT_NAME_PATTERN,
|
|
89
|
+
STORE_PROJECT_ID_PATTERN,
|
|
90
|
+
STORE_UUID_PATTERN,
|
|
91
|
+
deriveMountLabel,
|
|
92
|
+
detectNodeLocale,
|
|
93
|
+
globalConfigPath,
|
|
94
|
+
globalConfigSchema,
|
|
95
|
+
loadGlobalConfig,
|
|
96
|
+
mountedStoreSchema,
|
|
97
|
+
normalizeLocale,
|
|
98
|
+
requiredStoreEntrySchema,
|
|
99
|
+
resolveGlobalLocale,
|
|
100
|
+
resolveGlobalRoot,
|
|
101
|
+
saveGlobalConfig,
|
|
102
|
+
storeAliasSchema,
|
|
103
|
+
storeIdentitySchema,
|
|
104
|
+
storeKnowledgeTypeDir,
|
|
105
|
+
storeMountGroup,
|
|
106
|
+
storeMountNameSchema,
|
|
107
|
+
storeMountSubPath,
|
|
108
|
+
storeProjectSchema,
|
|
109
|
+
storeProjectsFileSchema,
|
|
110
|
+
storeRelativePath,
|
|
111
|
+
storeRelativePathForMount,
|
|
112
|
+
storeUuidSchema
|
|
113
|
+
} from "./chunk-2GLIAZ5M.js";
|
|
73
114
|
|
|
74
115
|
// src/schemas/agents-meta.ts
|
|
75
116
|
import { z } from "zod";
|
|
@@ -81,10 +122,8 @@ var KNOWLEDGE_TYPE_SINGULAR_TO_PLURAL = {
|
|
|
81
122
|
pitfall: "pitfalls",
|
|
82
123
|
process: "processes"
|
|
83
124
|
};
|
|
84
|
-
var AGENTS_META_LAYERS = ["L0", "L1", "L2"];
|
|
85
125
|
var AGENTS_META_TOPOLOGY_TYPES = ["mirror", "cross-cutting", "domain", "local", "global"];
|
|
86
126
|
var AGENTS_META_IDENTITY_SOURCES = ["declared", "derived"];
|
|
87
|
-
var agentsLayerSchema = z.enum(AGENTS_META_LAYERS);
|
|
88
127
|
var agentsTopologyTypeSchema = z.enum(AGENTS_META_TOPOLOGY_TYPES);
|
|
89
128
|
var agentsIdentitySourceSchema = z.enum(AGENTS_META_IDENTITY_SOURCES);
|
|
90
129
|
var ruleDescriptionSchema = z.object({
|
|
@@ -128,9 +167,6 @@ var ruleDescriptionSchema = z.object({
|
|
|
128
167
|
}).strict();
|
|
129
168
|
var ruleDescriptionIndexItemSchema = z.object({
|
|
130
169
|
stable_id: z.string(),
|
|
131
|
-
level: agentsLayerSchema,
|
|
132
|
-
required: z.boolean(),
|
|
133
|
-
selectable: z.boolean(),
|
|
134
170
|
description: ruleDescriptionSchema
|
|
135
171
|
}).strict();
|
|
136
172
|
var agentsMetaNodeBaseSchema = z.object({
|
|
@@ -140,10 +176,6 @@ var agentsMetaNodeBaseSchema = z.object({
|
|
|
140
176
|
hash: z.string(),
|
|
141
177
|
stable_id: z.string().optional(),
|
|
142
178
|
identity_source: agentsIdentitySourceSchema.optional(),
|
|
143
|
-
activation: z.object({
|
|
144
|
-
tier: z.enum(["always", "path", "description"]),
|
|
145
|
-
description: z.string().optional()
|
|
146
|
-
}).optional(),
|
|
147
179
|
description: ruleDescriptionSchema.optional(),
|
|
148
180
|
sections: z.array(z.string()).optional()
|
|
149
181
|
}).passthrough();
|
|
@@ -182,7 +214,6 @@ function withDerivedAgentsMetaNodeDefaults(node) {
|
|
|
182
214
|
const identitySource = isKnowledgeEntry ? "declared" : deriveAgentsMetaIdentitySource(node);
|
|
183
215
|
return {
|
|
184
216
|
...node,
|
|
185
|
-
level: node.level ?? deriveAgentsMetaLayer(node.file),
|
|
186
217
|
topology_type: node.topology_type ?? deriveAgentsMetaTopologyType(node.file),
|
|
187
218
|
stable_id: stableId,
|
|
188
219
|
identity_source: identitySource
|
|
@@ -226,34 +257,12 @@ function deriveAgentsMetaIdentitySource(node) {
|
|
|
226
257
|
const derivedStableId = deriveAgentsMetaStableId(node.file);
|
|
227
258
|
return node.stable_id !== void 0 && node.stable_id !== derivedStableId ? "declared" : "derived";
|
|
228
259
|
}
|
|
229
|
-
function deriveAgentsMetaLayer(file) {
|
|
230
|
-
const normalized = normalizePath(file);
|
|
231
|
-
if (normalized === "AGENTS.md") {
|
|
232
|
-
return "L0";
|
|
233
|
-
}
|
|
234
|
-
if (hasCrossCuttingSegment(normalized)) {
|
|
235
|
-
return "L1";
|
|
236
|
-
}
|
|
237
|
-
const depthSource = getDepthSource(normalized);
|
|
238
|
-
const directoryDepth = getDirectoryDepth(depthSource);
|
|
239
|
-
if (directoryDepth === 0) {
|
|
240
|
-
return "L0";
|
|
241
|
-
}
|
|
242
|
-
if (directoryDepth <= 2) {
|
|
243
|
-
return "L1";
|
|
244
|
-
}
|
|
245
|
-
return "L2";
|
|
246
|
-
}
|
|
247
260
|
function deriveAgentsMetaTopologyType(file) {
|
|
248
261
|
return hasCrossCuttingSegment(normalizePath(file)) ? "cross-cutting" : "mirror";
|
|
249
262
|
}
|
|
250
263
|
function getDepthSource(file) {
|
|
251
264
|
return file.startsWith(FABRIC_AGENTS_PREFIX) ? file.slice(FABRIC_AGENTS_PREFIX.length) : file;
|
|
252
265
|
}
|
|
253
|
-
function getDirectoryDepth(file) {
|
|
254
|
-
const segments = file.split("/").filter(Boolean);
|
|
255
|
-
return Math.max(segments.length - 1, 0);
|
|
256
|
-
}
|
|
257
266
|
function hasCrossCuttingSegment(file) {
|
|
258
267
|
return file.split("/").includes("_cross");
|
|
259
268
|
}
|
|
@@ -339,127 +348,35 @@ var humanLockFileSchema = z4.object({
|
|
|
339
348
|
});
|
|
340
349
|
|
|
341
350
|
// src/schemas/fabric-config.ts
|
|
342
|
-
import { z as z6 } from "zod";
|
|
343
|
-
|
|
344
|
-
// src/schemas/store.ts
|
|
345
351
|
import { z as z5 } from "zod";
|
|
346
|
-
var
|
|
347
|
-
var
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
store_uuid: storeUuidSchema,
|
|
352
|
-
// ISO-8601. When the store was first initialized.
|
|
353
|
-
created_at: z5.string(),
|
|
354
|
-
// Optional human-facing canonical alias baked into the store (e.g. the
|
|
355
|
-
// team picks "platform-kb"). Local per-machine aliases are resolved by the
|
|
356
|
-
// StoreResolver from config and may differ; this is the suggested default.
|
|
357
|
-
canonical_alias: z5.string().optional(),
|
|
358
|
-
// Optional one-line description surfaced in `store list` / onboarding.
|
|
359
|
-
description: z5.string().optional(),
|
|
360
|
-
// The semantic scopes this store is *allowed* to hold. A shared (team)
|
|
361
|
-
// store MUST NOT list "personal" (R5#3 privacy boundary, enforced at write
|
|
362
|
-
// time in P2). Open coordinate strings — see schemas/scope.ts.
|
|
363
|
-
allowed_scopes: z5.array(z5.string()).optional()
|
|
364
|
-
}).strict();
|
|
365
|
-
var STORE_PROJECT_ID_PATTERN = /^[a-z0-9_-]+$/u;
|
|
366
|
-
var storeProjectSchema = z5.object({
|
|
367
|
-
// Single scope segment forming the `project:<id>` coordinate. Immutable.
|
|
368
|
-
id: z5.string().regex(STORE_PROJECT_ID_PATTERN, "project id must be a single lowercase [a-z0-9_-] segment"),
|
|
369
|
-
// Optional human-facing label surfaced in `store project list`.
|
|
370
|
-
name: z5.string().optional(),
|
|
371
|
-
// ISO-8601. When the project was first registered in this store.
|
|
372
|
-
created_at: z5.string()
|
|
373
|
-
}).strict();
|
|
374
|
-
var storeProjectsFileSchema = z5.object({
|
|
375
|
-
projects: z5.array(storeProjectSchema).default([])
|
|
376
|
-
}).strict();
|
|
377
|
-
var requiredStoreEntrySchema = z5.object({
|
|
378
|
-
id: z5.string().min(1),
|
|
379
|
-
suggested_remote: z5.union([z5.string().min(1), z5.literal(PERSONAL_STORE_SENTINEL)]).optional()
|
|
352
|
+
var auditModeSchema = z5.enum(["strict", "warn", "off"]);
|
|
353
|
+
var clientPathsSchema = z5.object({
|
|
354
|
+
claudeCodeCLI: z5.string().optional(),
|
|
355
|
+
claudeCodeDesktop: z5.string().optional(),
|
|
356
|
+
codexCLI: z5.string().optional()
|
|
380
357
|
}).strict();
|
|
381
|
-
var
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
];
|
|
388
|
-
var
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
// derived agents.meta) because the counter ledger is non-derivable state that
|
|
395
|
-
// must travel with the store on clone: a fresh clone rebuilding from disk-max
|
|
396
|
-
// would re-mint a deleted entry's id and corrupt cite history (KT-DEC-0004
|
|
397
|
-
// monotonic invariant). Replaces the retired co-location
|
|
398
|
-
// <projectRoot>/.fabric/agents.meta.json#counters.
|
|
399
|
-
countersFile: "counters.json",
|
|
400
|
-
knowledgeDir: "knowledge",
|
|
401
|
-
bindingsDir: "bindings",
|
|
402
|
-
stateDir: "state"
|
|
403
|
-
};
|
|
404
|
-
var STORES_ROOT_DIR = "stores";
|
|
405
|
-
var GLOBAL_STATE_DIR = "state";
|
|
406
|
-
var GLOBAL_BINDINGS_DIR = "bindings";
|
|
407
|
-
function storeKnowledgeTypeDir(type) {
|
|
408
|
-
return `${STORE_LAYOUT.knowledgeDir}/${type}`;
|
|
409
|
-
}
|
|
410
|
-
function storeRelativePath(storeUuid) {
|
|
411
|
-
return `${STORES_ROOT_DIR}/${storeUuid}`;
|
|
412
|
-
}
|
|
413
|
-
var mountedStoreSchema = z5.object({
|
|
414
|
-
// Intrinsic identity of the mounted store (matches its store.json).
|
|
415
|
-
store_uuid: storeUuidSchema,
|
|
416
|
-
// Local per-machine alias the user references this store by (resolver maps
|
|
417
|
-
// alias → uuid). May differ from the store's canonical_alias.
|
|
418
|
-
alias: z5.string().min(1),
|
|
419
|
-
// Git remote locator for this clone, if any. Absent = local-only store
|
|
420
|
-
// (valid; doctor nudges to add a remote for backup — R5#5, P6).
|
|
421
|
-
remote: z5.string().min(1).optional(),
|
|
422
|
-
// v2.1.0-rc.1 P3: marks the implicit personal store (the one minted by
|
|
423
|
-
// `install --global`). Exactly one mounted store carries personal=true; it
|
|
424
|
-
// is the write target for personal-scope entries (R5#3) and always in the
|
|
425
|
-
// read-set (S11). Optional (no default) so the output type stays a plain
|
|
426
|
-
// optional — consumers coalesce `?? false` when building resolver input.
|
|
427
|
-
personal: z5.boolean().optional(),
|
|
428
|
-
// Whether writes are accepted into this store from this machine. Optional;
|
|
429
|
-
// consumers coalesce `?? true`. Shared stores cloned read-only set false.
|
|
430
|
-
writable: z5.boolean().optional()
|
|
358
|
+
var mcpPayloadLimitsSchema = z5.object({
|
|
359
|
+
warnBytes: z5.number().int().positive().optional(),
|
|
360
|
+
hardBytes: z5.number().int().positive().optional()
|
|
361
|
+
}).optional();
|
|
362
|
+
var selectionTokenTtlMsSchema = z5.number().int().min(3e4).max(36e5);
|
|
363
|
+
var planContextTopKSchema = z5.number().int().min(1).max(200);
|
|
364
|
+
var fabricLanguageSchema = z5.enum(["zh-CN", "en"]);
|
|
365
|
+
var defaultLayerFilterSchema = z5.enum(["team", "personal", "both"]);
|
|
366
|
+
var nudgeModeSchema = z5.enum(["silent", "minimal", "normal", "verbose"]);
|
|
367
|
+
var observeConfigSchema = z5.object({
|
|
368
|
+
session_start: z5.boolean().optional(),
|
|
369
|
+
pre_tool_use: z5.boolean().optional(),
|
|
370
|
+
stop: z5.boolean().optional()
|
|
431
371
|
}).strict();
|
|
432
|
-
var
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
stores: z5.array(mountedStoreSchema).optional().default([])
|
|
439
|
-
}).passthrough();
|
|
440
|
-
|
|
441
|
-
// src/schemas/fabric-config.ts
|
|
442
|
-
var auditModeSchema = z6.enum(["strict", "warn", "off"]);
|
|
443
|
-
var clientPathsSchema = z6.object({
|
|
444
|
-
claudeCodeCLI: z6.string().optional(),
|
|
445
|
-
claudeCodeDesktop: z6.string().optional(),
|
|
446
|
-
cursor: z6.string().optional(),
|
|
447
|
-
codexCLI: z6.string().optional()
|
|
372
|
+
var writeRouteSchema = z5.object({
|
|
373
|
+
scope: z5.string().regex(
|
|
374
|
+
SCOPE_COORDINATE_PATTERN,
|
|
375
|
+
"write route scope must be ':'-joined lowercase [a-z0-9_-] segments"
|
|
376
|
+
),
|
|
377
|
+
store: z5.string().min(1)
|
|
448
378
|
}).strict();
|
|
449
|
-
var
|
|
450
|
-
warnBytes: z6.number().int().positive().optional(),
|
|
451
|
-
hardBytes: z6.number().int().positive().optional()
|
|
452
|
-
}).optional();
|
|
453
|
-
var selectionTokenTtlMsSchema = z6.number().int().min(3e4).max(36e5);
|
|
454
|
-
var planContextTopKSchema = z6.number().int().min(1).max(200);
|
|
455
|
-
var fabricLanguageSchema = z6.enum([
|
|
456
|
-
"match-existing",
|
|
457
|
-
"zh-CN",
|
|
458
|
-
"en",
|
|
459
|
-
"zh-CN-hybrid"
|
|
460
|
-
]);
|
|
461
|
-
var defaultLayerFilterSchema = z6.enum(["team", "personal", "both"]);
|
|
462
|
-
var fabricConfigSchema = z6.object({
|
|
379
|
+
var fabricConfigSchema = z5.object({
|
|
463
380
|
clientPaths: clientPathsSchema.optional(),
|
|
464
381
|
// v2.1.0-rc.1 P0 (S13-projectid): the project's stable identity. A UUID
|
|
465
382
|
// bound at `fabric install` time; a remote-derived hash is only a SUGGESTED
|
|
@@ -468,19 +385,23 @@ var fabricConfigSchema = z6.object({
|
|
|
468
385
|
// fabric-config.json files simply lack it and the ProjectRootResolver mints
|
|
469
386
|
// one on next install. `.fabric/fabric-config.json` carrying this field is
|
|
470
387
|
// also the upward marker the ProjectRootResolver searches for (S15/S32).
|
|
471
|
-
project_id:
|
|
388
|
+
project_id: z5.string().optional(),
|
|
389
|
+
// Store-only runtime binding identity. Defaults to project_id when omitted,
|
|
390
|
+
// but worktrees / sandboxes can set this to isolate hook/runtime state while
|
|
391
|
+
// keeping the same committed project identity.
|
|
392
|
+
workspace_binding_id: z5.string().optional(),
|
|
472
393
|
// v2.1.0-rc.1 P0 (S59/B3): the stores this repo expects mounted. Each entry
|
|
473
394
|
// names a store by alias/UUID with an optional suggested_remote (or the
|
|
474
395
|
// `$personal` sentinel). Drives the read-set (required_stores ∪ implicit
|
|
475
396
|
// personal, S11/S54) and `clone`'s missing-store onboarding (S51). Optional
|
|
476
397
|
// + absent → read-set is just the implicit personal store.
|
|
477
|
-
required_stores:
|
|
398
|
+
required_stores: z5.array(requiredStoreEntrySchema).optional(),
|
|
478
399
|
// v2.1.0-rc.1 P3 (S60 / `store switch-write`): alias of the store that
|
|
479
400
|
// non-personal-scope writes land in for this project. Set by
|
|
480
401
|
// `fabric store switch-write <alias>`; consumed as the resolver's
|
|
481
402
|
// activeWriteAlias. Absent → no active write store yet. Personal-scope
|
|
482
403
|
// writes always target the implicit personal store regardless (R5#3).
|
|
483
|
-
active_write_store:
|
|
404
|
+
active_write_store: z5.string().optional(),
|
|
484
405
|
// v2.1 global-refactor (W1/A2 — store project registry): the project this repo
|
|
485
406
|
// currently participates in, as the SINGLE scope segment forming the
|
|
486
407
|
// `project:<id>` coordinate (schemas/scope.ts). Set by `store bind --project
|
|
@@ -489,7 +410,12 @@ var fabricConfigSchema = z6.object({
|
|
|
489
410
|
// - recall: keep `project:<active_project>` + non-project coords, drop other
|
|
490
411
|
// `project:*` entries (G-FILTER).
|
|
491
412
|
// Absent → the repo has no project binding; recall does not project-filter.
|
|
492
|
-
active_project:
|
|
413
|
+
active_project: z5.string().optional(),
|
|
414
|
+
// Global Store Topology: scope-aware write routing for multi shared/org stores.
|
|
415
|
+
// Personal scope ignores these routes and always resolves to the implicit
|
|
416
|
+
// personal store. `active_write_store` remains a backward-compatible fallback.
|
|
417
|
+
write_routes: z5.array(writeRouteSchema).optional(),
|
|
418
|
+
default_write_store: z5.string().optional(),
|
|
493
419
|
// rc.17 (R-cut): the dev/test fixture-path config field was removed
|
|
494
420
|
// end-to-end. The `EXTERNAL_FIXTURE_PATH` env var is now the sole source
|
|
495
421
|
// consumed by `resolveDevMode()`. No z.preprocess alias — pre-rc.17
|
|
@@ -497,14 +423,23 @@ var fabricConfigSchema = z6.object({
|
|
|
497
423
|
// the lenient root parser (no .strict() at root). Pre-user clean-slate per
|
|
498
424
|
// memory/feedback_clean_slate.md; mirrors the rc.12 hard-rename precedent
|
|
499
425
|
// documented above.
|
|
500
|
-
scanIgnores:
|
|
426
|
+
scanIgnores: z5.array(z5.string()).optional(),
|
|
501
427
|
audit_mode: auditModeSchema.optional(),
|
|
502
428
|
mcpPayloadLimits: mcpPayloadLimitsSchema,
|
|
503
|
-
//
|
|
504
|
-
//
|
|
505
|
-
//
|
|
506
|
-
|
|
429
|
+
// grill-6fixes (D1): `fabric_language` is no longer a per-project field —
|
|
430
|
+
// language is a single machine-wide tone in `~/.fabric/fabric-global.json`.
|
|
431
|
+
// The root parser is lenient (no .strict()), so any stale `fabric_language`
|
|
432
|
+
// key left in an existing project config is silently dropped.
|
|
507
433
|
default_layer_filter: defaultLayerFilterSchema.optional().default("both"),
|
|
434
|
+
// v2.2 dual-sink (Goal A / D4): human-output preset. See nudgeModeSchema for
|
|
435
|
+
// the level semantics + the flow ⊥ observation invariant (nudge_mode never
|
|
436
|
+
// touches the AI additionalContext sink). Default "normal" preserves the
|
|
437
|
+
// pre-dual-sink human visibility so existing dogfood repos see no regression.
|
|
438
|
+
nudge_mode: nudgeModeSchema.optional().default("normal"),
|
|
439
|
+
// v2.2 dual-sink (Goal A / D4): per-event human-output overrides. A set value
|
|
440
|
+
// wins over the nudge_mode preset for that event; absent events fall back to
|
|
441
|
+
// the preset. AI sink unaffected (same invariant as nudge_mode).
|
|
442
|
+
observe: observeConfigSchema.optional(),
|
|
508
443
|
// Cooldown for the fabric-hint Stop hook (formerly archive-hint, renamed in
|
|
509
444
|
// rc.5 TASK-010). After ANY of the three signals (archive / review / import)
|
|
510
445
|
// fires, that signal stays silent for this many hours regardless of state
|
|
@@ -512,7 +447,7 @@ var fabricConfigSchema = z6.object({
|
|
|
512
447
|
// day if the user keeps ignoring it." Set to 24 to align with the archive
|
|
513
448
|
// trigger threshold. The legacy `archive_hint_` key is retained for backward
|
|
514
449
|
// compat with existing user fabric-config.json files.
|
|
515
|
-
archive_hint_cooldown_hours:
|
|
450
|
+
archive_hint_cooldown_hours: z5.number().int().positive().optional().default(12),
|
|
516
451
|
// Underseed-node threshold for the fabric-hint Stop hook's import signal
|
|
517
452
|
// (rc.5 TASK-010). When the canonical knowledge node count is strictly less
|
|
518
453
|
// than this value AND a successful `init_scan_completed` event happened at
|
|
@@ -521,7 +456,7 @@ var fabricConfigSchema = z6.object({
|
|
|
521
456
|
// the rule-of-thumb that a workspace with fewer than ten knowledge entries
|
|
522
457
|
// is below the floor for plan_context retrieval to be meaningful. Also
|
|
523
458
|
// consumed by `doctor` lint #22 (knowledge_underseeded).
|
|
524
|
-
underseed_node_threshold:
|
|
459
|
+
underseed_node_threshold: z5.number().int().positive().optional().default(10),
|
|
525
460
|
// Edit-count threshold for the fabric-hint Stop hook's Signal A
|
|
526
461
|
// (rc.6 TASK-022 / E5). Signal A fires when EITHER (a) >=24h have elapsed
|
|
527
462
|
// since the last `knowledge_proposed` event, OR (b) >=archive_edit_threshold
|
|
@@ -532,102 +467,102 @@ var fabricConfigSchema = z6.object({
|
|
|
532
467
|
// there is probably something worth archiving"; lowered values nag more
|
|
533
468
|
// aggressively, higher values rely on the 24h fallback. Missing or absent
|
|
534
469
|
// edit-counter file degrades safely to the 24h-only path.
|
|
535
|
-
archive_edit_threshold:
|
|
470
|
+
archive_edit_threshold: z5.number().int().positive().optional().default(20),
|
|
536
471
|
// rc.7 T7: hours-since-last-knowledge_proposed cutoff for Signal A's
|
|
537
472
|
// time branch. Was hardcoded as 24 in fabric-hint.cjs's THRESHOLD_HOURS;
|
|
538
473
|
// externalized so chatty workspaces can lower the bar and quiet ones can
|
|
539
474
|
// raise it. Default 24 preserves rc.6 behavior. See docs/configuration.md.
|
|
540
|
-
archive_hint_hours:
|
|
475
|
+
archive_hint_hours: z5.number().int().positive().optional().default(24),
|
|
541
476
|
// rc.7 T7: pending-count cutoff for Signal B (review skill). Was
|
|
542
477
|
// hardcoded as 10 in fabric-hint.cjs's THRESHOLD_PENDING_COUNT.
|
|
543
478
|
// Default 10 preserves rc.6 behavior. See docs/configuration.md for
|
|
544
479
|
// small/medium/large repo recommendations.
|
|
545
|
-
review_hint_pending_count:
|
|
480
|
+
review_hint_pending_count: z5.number().int().positive().optional().default(10),
|
|
546
481
|
// rc.7 T7: pending-age cutoff (in days) for Signal B (review skill).
|
|
547
482
|
// Was hardcoded as 7 in fabric-hint.cjs's THRESHOLD_PENDING_AGE_DAYS.
|
|
548
483
|
// Default 7 preserves rc.6 behavior. See docs/configuration.md.
|
|
549
|
-
review_hint_pending_age_days:
|
|
484
|
+
review_hint_pending_age_days: z5.number().int().positive().optional().default(7),
|
|
550
485
|
// rc.7 T7 + T10 pre-wiring: days-since-last-doctor cutoff for the future
|
|
551
486
|
// Signal D (maintenance hint). T10 will consume this to decide when the
|
|
552
487
|
// fabric-hint Stop hook surfaces a "run `fabric doctor`" reminder.
|
|
553
488
|
// Default 14 reflects a fortnightly cadence — long enough to avoid nag,
|
|
554
489
|
// short enough to catch index drift before it compounds.
|
|
555
|
-
maintenance_hint_days:
|
|
490
|
+
maintenance_hint_days: z5.number().int().positive().optional().default(14),
|
|
556
491
|
// rc.7 T7 + T10 pre-wiring: cooldown between Signal D reminders, in
|
|
557
492
|
// days. Once Signal D fires, it stays silent for this many days even if
|
|
558
493
|
// the user doesn't run doctor. Default 7 keeps the reminder weekly at
|
|
559
494
|
// worst — pairing 14d trigger + 7d cooldown means at most ~2 reminders
|
|
560
495
|
// per month for a workspace that ignores them.
|
|
561
|
-
maintenance_hint_cooldown_days:
|
|
496
|
+
maintenance_hint_cooldown_days: z5.number().int().positive().optional().default(7),
|
|
562
497
|
// rc.9+ (skill-contract-fix B1): first-run import window in months. The
|
|
563
498
|
// `fabric-import` skill scans this many months of git history on the very
|
|
564
499
|
// first invocation (when no prior `import_run_completed` event exists).
|
|
565
500
|
// Default 60 (~5 years) captures the bulk of a mature repo's signal in
|
|
566
501
|
// one pass; small / fresh repos can lower to 12-24 with no loss.
|
|
567
|
-
import_window_first_run_months:
|
|
502
|
+
import_window_first_run_months: z5.number().int().min(1).optional().default(60),
|
|
568
503
|
// rc.9+ (skill-contract-fix B1): rerun import window in months. After
|
|
569
504
|
// the first successful import, subsequent runs only scan this many
|
|
570
505
|
// recent months — assumed everything older has already been crystallized
|
|
571
506
|
// into pending or canonical knowledge. Default 2 keeps incremental cost
|
|
572
507
|
// low; raise to 6 if the workspace pauses fabric-import for long stretches.
|
|
573
|
-
import_window_rerun_months:
|
|
508
|
+
import_window_rerun_months: z5.number().int().min(1).optional().default(2),
|
|
574
509
|
// rc.9+ (skill-contract-fix B1): hard cap on pending entries produced
|
|
575
510
|
// per fabric-import invocation. Prevents one run from dumping hundreds
|
|
576
511
|
// of proposals when a backfill window is wide open. Default 10 matches
|
|
577
512
|
// the rule-of-thumb "human can triage ~10 pending entries in one
|
|
578
513
|
// review pass." Range 1-50.
|
|
579
|
-
import_max_pending_per_run:
|
|
514
|
+
import_max_pending_per_run: z5.number().int().min(1).max(50).optional().default(10),
|
|
580
515
|
// rc.9+ (skill-contract-fix B1): hard cap on commits scanned per
|
|
581
516
|
// fabric-import invocation. Bounds runtime on monorepos with high
|
|
582
517
|
// commit velocity. Default 500 covers ~2 months of typical churn;
|
|
583
518
|
// range 50-2000. Hitting the cap mid-window is logged but non-fatal.
|
|
584
|
-
import_max_commits_scan:
|
|
519
|
+
import_max_commits_scan: z5.number().int().min(50).max(2e3).optional().default(500),
|
|
585
520
|
// rc.9+ (skill-contract-fix B1): canonical-node count above which
|
|
586
521
|
// fabric-import's pre-flight should warn / suggest review instead of
|
|
587
522
|
// proceeding. A workspace with 50+ canonical entries usually benefits
|
|
588
523
|
// more from `fabric-review` to consolidate than from importing more.
|
|
589
524
|
// Default 50; raise to 100+ for large polyglot repos.
|
|
590
|
-
import_skip_canonical_threshold:
|
|
525
|
+
import_skip_canonical_threshold: z5.number().int().positive().optional().default(50),
|
|
591
526
|
// rc.9+ (skill-contract-fix B1): max candidate entries surfaced per
|
|
592
527
|
// fabric-archive batch (one invocation of the skill). Pagination knob
|
|
593
528
|
// for the archive UI flow. Default 8 keeps each batch reviewable in
|
|
594
529
|
// one sitting; raise for large repos with high archive throughput.
|
|
595
|
-
archive_max_candidates_per_batch:
|
|
530
|
+
archive_max_candidates_per_batch: z5.number().int().positive().optional().default(8),
|
|
596
531
|
// rc.9+ (skill-contract-fix B1): max recently-touched paths included
|
|
597
532
|
// in fabric-archive's "relevant context" lookup. Limits the size of
|
|
598
533
|
// the path-relevance digest the skill emits when ranking candidates.
|
|
599
534
|
// Default 20; large repos with deep directory fan-out can raise to
|
|
600
535
|
// 50+ if archive candidates feel under-contextualized.
|
|
601
|
-
archive_max_recent_paths:
|
|
536
|
+
archive_max_recent_paths: z5.number().int().positive().optional().default(20),
|
|
602
537
|
// rc.9+ (skill-contract-fix B1): max prior fabric-archive sessions
|
|
603
538
|
// summarised in the digest the skill loads on start. Prevents the
|
|
604
539
|
// digest from ballooning past the model context budget on workspaces
|
|
605
540
|
// that have archived repeatedly. Default 10; lower if context pressure
|
|
606
541
|
// bites, raise if you want longer-range archive trend visibility.
|
|
607
|
-
archive_digest_max_sessions:
|
|
542
|
+
archive_digest_max_sessions: z5.number().int().positive().optional().default(10),
|
|
608
543
|
// rc.9+ (skill-contract-fix B1): max review results returned per
|
|
609
544
|
// topic when `fabric-review` clusters pending entries. Pagination
|
|
610
545
|
// knob analogous to archive_max_candidates_per_batch but scoped to
|
|
611
546
|
// each topic cluster. Default 8; raise to 15-20 for large repos
|
|
612
547
|
// where each topic legitimately groups many pending entries.
|
|
613
|
-
review_topic_result_cap:
|
|
548
|
+
review_topic_result_cap: z5.number().int().positive().optional().default(8),
|
|
614
549
|
// rc.9+ (skill-contract-fix B1): age threshold (in days) above which
|
|
615
550
|
// a pending entry is considered "stale" by fabric-review and surfaced
|
|
616
551
|
// for explicit resolve-or-drop decision. Default 14; tighter than the
|
|
617
552
|
// 7d Signal-B trigger because review specifically targets the long
|
|
618
553
|
// tail. Large repos with slower cadence can raise to 30.
|
|
619
|
-
review_stale_pending_days:
|
|
554
|
+
review_stale_pending_days: z5.number().int().positive().optional().default(14),
|
|
620
555
|
// v2.0.0-rc.34 TASK-05: reverse-unarchive opt-in. When true, callers of the
|
|
621
556
|
// `unarchiveKnowledge` primitive (and any future doctor auto-detect lint built
|
|
622
557
|
// on top) will execute the file move + ledger emit. When false (default),
|
|
623
558
|
// the same callers MUST short-circuit before any mutation — the primitive is
|
|
624
559
|
// shipped but inert until explicitly enabled. Opt-in posture mirrors the
|
|
625
560
|
// archive-flow precedent: destructive-ish file moves stay behind a flag.
|
|
626
|
-
reverse_unarchive_enabled:
|
|
561
|
+
reverse_unarchive_enabled: z5.boolean().optional().default(false),
|
|
627
562
|
// v2.0.0-rc.34 TASK-05: forces `unarchiveKnowledge` into dry-run mode even
|
|
628
563
|
// when called with `options.dryRun=false`. Lets operators preview a
|
|
629
564
|
// restoration pass before flipping `reverse_unarchive_enabled` to true.
|
|
630
|
-
reverse_unarchive_dry_run:
|
|
565
|
+
reverse_unarchive_dry_run: z5.boolean().optional().default(false),
|
|
631
566
|
// v2.0.0-rc.34 TASK-06: long-session cite-policy evict window in user-prompt
|
|
632
567
|
// turns. UserPromptSubmit hook (Claude Code only) maintains a per-session
|
|
633
568
|
// counter and re-injects the cite contract reminder via
|
|
@@ -635,7 +570,7 @@ var fabricConfigSchema = z6.object({
|
|
|
635
570
|
// Default 0 = OFF (opt-in). Recommend 10-20 for active sessions; 5 for
|
|
636
571
|
// high-contract-criticality projects. Other strategies (time-based,
|
|
637
572
|
// token-budget) deferred to rc.35 per plan locked-decisions 2026-05-26.
|
|
638
|
-
cite_evict_interval:
|
|
573
|
+
cite_evict_interval: z5.number().int().min(0).optional().default(0),
|
|
639
574
|
// v2.1 ⑤ cite-redesign (P5): recall-based cite-accounting hook config. The
|
|
640
575
|
// rc.34 cite_evict_interval turn-counter above is superseded by the
|
|
641
576
|
// PreToolUse(Edit/Write) recall-aware nudge in cite-policy-evict.cjs; the old
|
|
@@ -645,21 +580,21 @@ var fabricConfigSchema = z6.object({
|
|
|
645
580
|
// the cite_evict_interval=0 opt-out convention). `cite_recall_window_minutes`
|
|
646
581
|
// bounds how far back an in-session fab_recall counts as "informing" the edit
|
|
647
582
|
// (default 30; 0 = unbounded).
|
|
648
|
-
cite_recall_nudge:
|
|
649
|
-
cite_recall_window_minutes:
|
|
583
|
+
cite_recall_nudge: z5.boolean().optional().default(true),
|
|
584
|
+
cite_recall_window_minutes: z5.number().int().min(0).optional().default(30),
|
|
650
585
|
// F2: glob exemptions for the cite nudge (cite-policy-evict.cjs). Edit paths
|
|
651
586
|
// matching any glob skip the "改前先 fab_recall" nudge — meta/orchestration
|
|
652
587
|
// files (e.g. `.workflow/` scratchpads) are not source the cite policy
|
|
653
588
|
// governs. MERGED with the hook's built-in [".workflow/**"] default; an
|
|
654
589
|
// omitted/empty value keeps just that default. `*` = within a path segment,
|
|
655
590
|
// `**` = across segments.
|
|
656
|
-
cite_nudge_ignore_globs:
|
|
591
|
+
cite_nudge_ignore_globs: z5.array(z5.string()).optional(),
|
|
657
592
|
// v2.1 ④ conflict-detection (P4): bm25 content-similarity threshold (0..1)
|
|
658
593
|
// for the knowledge-conflict lint (`fabric doctor --lint-conflicts`). A
|
|
659
594
|
// same-(type,layer) pair whose normalized bm25 similarity reaches this floor
|
|
660
595
|
// is surfaced as a candidate (possible duplicate OR conflict). Conservative
|
|
661
596
|
// default 0.5 — raise to reduce noise, lower to catch looser pairs.
|
|
662
|
-
conflict_lint_similarity_threshold:
|
|
597
|
+
conflict_lint_similarity_threshold: z5.number().min(0).max(1).optional().default(0.5),
|
|
663
598
|
// v2.0.0-rc.22 Scope A T3: sliding-window retention (in days) for the
|
|
664
599
|
// event ledger rotation primitive (`rotateEventLedgerIfNeeded`). Lines
|
|
665
600
|
// whose `ts` is older than `now - fabric_event_retention_days * 86_400_000`
|
|
@@ -672,7 +607,7 @@ var fabricConfigSchema = z6.object({
|
|
|
672
607
|
// Mirrors cite-policy precedent of locking enum-style numeric tunables
|
|
673
608
|
// to a small literal set (vs free `.positive()`) to prevent fat-finger
|
|
674
609
|
// misconfig.
|
|
675
|
-
fabric_event_retention_days:
|
|
610
|
+
fabric_event_retention_days: z5.union([z5.literal(7), z5.literal(30), z5.literal(90)]).optional(),
|
|
676
611
|
// v2.0.0-rc.23 TASK-014 (F8c): onboard slot opt-out list. Tracks slot
|
|
677
612
|
// names the user explicitly dismissed during fabric-archive's first-run
|
|
678
613
|
// onboard phase (or via `fabric config dismiss-slot <slot>`). Dismissed
|
|
@@ -689,7 +624,7 @@ var fabricConfigSchema = z6.object({
|
|
|
689
624
|
//
|
|
690
625
|
// Default `[]` keeps the field optional on existing configs — fresh
|
|
691
626
|
// installs land with no opt-outs.
|
|
692
|
-
onboard_slots_opted_out:
|
|
627
|
+
onboard_slots_opted_out: z5.array(z5.string()).optional().default([]),
|
|
693
628
|
// v2.0.0-rc.33 W2-1 (P0-9): TopK upper bound for the broad SessionStart hint
|
|
694
629
|
// banner emitted by knowledge-hint-broad.cjs. After plan-context-hint returns
|
|
695
630
|
// its full broad-scoped index, the hook slices the entries to this many
|
|
@@ -701,20 +636,29 @@ var fabricConfigSchema = z6.object({
|
|
|
701
636
|
// Range 1..50; values above 20 effectively disable the cap because the
|
|
702
637
|
// TRUNCATION_THRESHOLD=12 grouped-render kicks in. Mirrors the rc.7 T7 +
|
|
703
638
|
// archive_max_* pattern of externalizing previously-hardcoded thresholds.
|
|
704
|
-
hint_broad_top_k:
|
|
639
|
+
hint_broad_top_k: z5.number().int().min(1).max(50).optional().default(8),
|
|
705
640
|
// v2.2 HK2-degrade (W2-T2): char budget for the rendered SessionStart broad-menu
|
|
706
641
|
// body — the final rung of the degradation ladder after the hint_broad_top_k
|
|
707
642
|
// count slice. Once the rendered entry/group lines exceed this, the tail
|
|
708
643
|
// collapses to a single "N more omitted" marker so a large corpus cannot blow
|
|
709
644
|
// the agent's working memory. Default 2000 (~one screenful); 0 disables the
|
|
710
645
|
// budget. Read by knowledge-hint-broad.cjs via readConfigNumber. Range 0..20000.
|
|
711
|
-
hint_broad_budget_chars:
|
|
646
|
+
hint_broad_budget_chars: z5.number().int().min(0).max(2e4).optional().default(2e3),
|
|
647
|
+
// W4-1 (KT-DEC-0028 / KT-MOD-0001): scale backstop for the FULL broad index.
|
|
648
|
+
// After W2-1 retired the hint_broad_top_k hard cap, the broad banner shows
|
|
649
|
+
// every broad entry (completeness); this is the only guard — once a store's
|
|
650
|
+
// rendered broad index exceeds this many lines the overflow tail folds into a
|
|
651
|
+
// single drift marker. The doctor `broad-index-drift` lint (W4-2) warns at 80%
|
|
652
|
+
// of this value per store so the corpus can be pruned (fabric-audit) BEFORE the
|
|
653
|
+
// banner silently truncates. Default 50; range 20..500 (read inline by
|
|
654
|
+
// knowledge-hint-broad.cjs#readBroadIndexBackstop with the same bounds).
|
|
655
|
+
broad_index_backstop: z5.number().int().min(20).max(500).optional().default(50),
|
|
712
656
|
// v2.0.0-rc.37 NEW-16: durable per-signal dismiss for the fabric-hint Stop
|
|
713
657
|
// hook nudges. Any signal type listed here is suppressed at emit time across
|
|
714
658
|
// all sessions (the session-scoped sibling lives in a .fabric/.cache sidecar
|
|
715
659
|
// written on request). Mirrors the cite_evict_interval=0 opt-out convention —
|
|
716
660
|
// a knob for an existing surface, not a new feature. Unknown types ignored.
|
|
717
|
-
hint_dismiss_signals:
|
|
661
|
+
hint_dismiss_signals: z5.array(z5.enum(["archive", "review", "import", "maintenance"])).optional(),
|
|
718
662
|
// v2.1 ADJ-NEWN-4: user-override escape hatches for the two strong behavioral
|
|
719
663
|
// policies (cite-before-edit + self-archive). The strong policies can make an
|
|
720
664
|
// agent feel like a "stubborn parrot" (D2 user-in-control red line); these
|
|
@@ -726,15 +670,15 @@ var fabricConfigSchema = z6.object({
|
|
|
726
670
|
// surface, mirroring the cite_evict_interval=0 / hint_dismiss_signals opt-out
|
|
727
671
|
// convention, NOT a new feature. Wave3 J32 will quantify the friction these
|
|
728
672
|
// relieve; until then they ship as inert-safe opt-outs.
|
|
729
|
-
cite_policy_enabled:
|
|
730
|
-
self_archive_policy_enabled:
|
|
673
|
+
cite_policy_enabled: z5.boolean().optional().default(true),
|
|
674
|
+
self_archive_policy_enabled: z5.boolean().optional().default(true),
|
|
731
675
|
// v2.0.0-rc.33 W2-1 (P0-9): TopK upper bound for the narrow PreToolUse hint
|
|
732
676
|
// emitted by knowledge-hint-narrow.cjs. After filtering to entries whose
|
|
733
677
|
// `relevance_scope === "narrow"` (rc.27 TASK-005 audit §2.5 fix), the hook
|
|
734
678
|
// slices to this many before the E3 emit-gate / renderSummary pipeline.
|
|
735
679
|
// Default 5 keeps each per-Edit hint terse — five lines max so the agent's
|
|
736
680
|
// working memory is not displaced by an unwieldy banner. Range 1..20.
|
|
737
|
-
hint_narrow_top_k:
|
|
681
|
+
hint_narrow_top_k: z5.number().int().min(1).max(20).optional().default(5),
|
|
738
682
|
// v2.0.0-rc.33 W2-1 (P0-9): per-file dedup window (in PreToolUse turns) for
|
|
739
683
|
// the narrow hint. Same (file_path, stable_id) tuple stays silent for this
|
|
740
684
|
// many turns even when the E3 cross-session cache would otherwise re-emit.
|
|
@@ -744,7 +688,7 @@ var fabricConfigSchema = z6.object({
|
|
|
744
688
|
// Storage: .fabric/.cache/narrow-dedup-window.json — distinct from session-
|
|
745
689
|
// hints cache so a window-only suppression does not poison cross-session
|
|
746
690
|
// dedupe semantics.
|
|
747
|
-
hint_narrow_dedup_window_turns:
|
|
691
|
+
hint_narrow_dedup_window_turns: z5.number().int().min(1).max(50).optional().default(5),
|
|
748
692
|
// v2.0.0-rc.33 W2-5 (P1-8): cooldown between broad SessionStart hint emits,
|
|
749
693
|
// in hours. Distinct from the archive_hint_cooldown_hours that gates the
|
|
750
694
|
// fabric-hint Stop hook — knowledge-hint-broad re-fires on every
|
|
@@ -753,14 +697,14 @@ var fabricConfigSchema = z6.object({
|
|
|
753
697
|
// menu at most once per hour"; 0 means "no cooldown, current behavior."
|
|
754
698
|
// Range 0..168 (one week). Stored alongside fabric-hint's cooldown cache
|
|
755
699
|
// under a distinct knowledge-hint-broad key.
|
|
756
|
-
hint_broad_cooldown_hours:
|
|
700
|
+
hint_broad_cooldown_hours: z5.number().int().min(0).max(168).optional().default(0),
|
|
757
701
|
// v2.0.0-rc.33 W2-5 (P1-8): cooldown for the narrow PreToolUse hint.
|
|
758
702
|
// Same shape as hint_broad_cooldown_hours but applies to per-Edit hint
|
|
759
703
|
// re-emission across the cooldown window — independent of E3 session-
|
|
760
704
|
// hints dedupe. Default 0 preserves rc.32 behavior; set to e.g. 1 to
|
|
761
705
|
// throttle hint frequency during rapid-fire editing sprints. Range
|
|
762
706
|
// 0..168 (one week).
|
|
763
|
-
hint_narrow_cooldown_hours:
|
|
707
|
+
hint_narrow_cooldown_hours: z5.number().int().min(0).max(168).optional().default(0),
|
|
764
708
|
// v2.0.0-rc.33 W4-B3 (T5 P2): per-maturity inactivity thresholds (days)
|
|
765
709
|
// driving orphan_demote. Hardcoded at proven=90/verified=30/draft=14 in
|
|
766
710
|
// rc.32; chatty workspaces want them tighter, slow ones want them looser.
|
|
@@ -768,26 +712,19 @@ var fabricConfigSchema = z6.object({
|
|
|
768
712
|
// chosen so a typo can't accidentally disable the lint (min 1).
|
|
769
713
|
//
|
|
770
714
|
// v2.2 W3-T5 (F-MATURITY-ENDORSED): the canonical maturity enum is
|
|
771
|
-
// draft/verified/proven (KT-DEC-0005)
|
|
772
|
-
//
|
|
773
|
-
//
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
orphan_demote_proven_days: z6.number().int().min(1).max(3650).optional(),
|
|
778
|
-
orphan_demote_verified_days: z6.number().int().min(1).max(3650).optional(),
|
|
779
|
-
orphan_demote_draft_days: z6.number().int().min(1).max(3650).optional(),
|
|
780
|
-
// Legacy aliases (deprecated; map to proven/verified). Kept so existing
|
|
781
|
-
// configs do not silently lose their tuning.
|
|
782
|
-
orphan_demote_stable_days: z6.number().int().min(1).max(3650).optional(),
|
|
783
|
-
orphan_demote_endorsed_days: z6.number().int().min(1).max(3650).optional(),
|
|
715
|
+
// draft/verified/proven (KT-DEC-0005). These threshold keys use the canonical
|
|
716
|
+
// vocabulary; the loader maps proven→stable / verified→endorsed onto the
|
|
717
|
+
// doctor's internal orphan_demote ladder.
|
|
718
|
+
orphan_demote_proven_days: z5.number().int().min(1).max(3650).optional(),
|
|
719
|
+
orphan_demote_verified_days: z5.number().int().min(1).max(3650).optional(),
|
|
720
|
+
orphan_demote_draft_days: z5.number().int().min(1).max(3650).optional(),
|
|
784
721
|
// v2.0.0-rc.33 W4-A3 (T4 P2): per-entry summary truncation length used by
|
|
785
722
|
// knowledge-hint-{broad,narrow}.cjs. Hard-coded at 80 chars in rc.32 — too
|
|
786
723
|
// short for entries with parameterized summaries (e.g. "Use bcrypt with
|
|
787
724
|
// cost=12 for password hashing"), too long for terse pitfalls. Range 40..240;
|
|
788
725
|
// default 80 preserves rc.32 behavior. Both hooks read the same key so the
|
|
789
726
|
// banner styling stays consistent across SessionStart + PreToolUse.
|
|
790
|
-
hint_summary_max_len:
|
|
727
|
+
hint_summary_max_len: z5.number().int().min(40).max(240).optional().default(80),
|
|
791
728
|
// v2.0.0-rc.33 W2-6 (P0-7 + P0-8): when true, knowledge-hint hooks emit
|
|
792
729
|
// their banners as `hookSpecificOutput.additionalContext` JSON on stdout
|
|
793
730
|
// (per Claude Code PreToolUse hook contract — see
|
|
@@ -797,7 +734,7 @@ var fabricConfigSchema = z6.object({
|
|
|
797
734
|
// coverage focus (rc.32 baseline 3.1% → primary cause: reminders never
|
|
798
735
|
// entered model context). Set false to revert to legacy stderr-only mode
|
|
799
736
|
// for hosts that don't honor the JSON contract.
|
|
800
|
-
hint_reminder_to_context:
|
|
737
|
+
hint_reminder_to_context: z5.boolean().optional().default(true),
|
|
801
738
|
// v2.0.0-rc.29 TASK-008 (BUG-F3): selection-token TTL override. The
|
|
802
739
|
// `fab_plan_context` MCP tool hands clients a `selection_token` whose default
|
|
803
740
|
// 5-minute lifetime (`SELECTION_TOKEN_TTL_MS` at
|
|
@@ -825,19 +762,27 @@ var fabricConfigSchema = z6.object({
|
|
|
825
762
|
// up together. Per-field knobs (plan_context_top_k, mcpPayloadLimits.*,
|
|
826
763
|
// hint_broad_budget_chars) still override the profile when set. See
|
|
827
764
|
// retrieval-budget.ts (resolveRetrievalBudget) for the resolution order.
|
|
828
|
-
retrieval_budget_profile:
|
|
765
|
+
retrieval_budget_profile: z5.enum(["conservative", "balanced", "generous"]).optional(),
|
|
766
|
+
// grill-report C-009 / R2-R5 mitigation knob: per-field override for the
|
|
767
|
+
// fab_recall body-tier budget (bytes). Absent → derived from the profile
|
|
768
|
+
// (balanced = 4096). Bump it if the lean default drops too many bodies and the
|
|
769
|
+
// AI is not following up with fab_get_knowledge_sections (R2 observation).
|
|
770
|
+
// Range 256B..1MB — below 256B even one body never fits; above 1MB defeats the
|
|
771
|
+
// whole lean-recall purpose. Overrides the profile when set, like the other
|
|
772
|
+
// per-field knobs.
|
|
773
|
+
recall_body_budget_bytes: z5.number().int().min(256).max(1048576).optional(),
|
|
829
774
|
// v2.2 C2-vector (W2-T7): OPTIONAL dense-embedding semantic retrieval, layered
|
|
830
775
|
// as a recall supplement after BM25. Default OFF (`--no-embed` is the baseline);
|
|
831
776
|
// requires the operator to install the optional `fastembed` package — absent →
|
|
832
777
|
// text-only fallback. Never grows the default install footprint.
|
|
833
|
-
embed_enabled:
|
|
778
|
+
embed_enabled: z5.boolean().optional().default(false),
|
|
834
779
|
// Weight applied to the 0..1 cosine similarity before it joins the additive
|
|
835
780
|
// score. Capped at 49 — strictly BELOW BM25_WEIGHT (50) — so a perfect vector
|
|
836
781
|
// match (weight × 1) can never outscore a single strong BM25 term match. This
|
|
837
782
|
// ENFORCES the "vectors supplement, never override lexical relevance"
|
|
838
783
|
// invariant in the schema rather than leaving it to a comment (W2-REVIEW codex
|
|
839
784
|
// MED-4). Range 0..49; default 30.
|
|
840
|
-
embed_weight:
|
|
785
|
+
embed_weight: z5.number().int().min(0).max(49).optional().default(30),
|
|
841
786
|
// v2.1 ③ vector-chinese-model (P3): which fastembed model to load. The prior
|
|
842
787
|
// code pinned fastembed's English default (bge-small-en-v1.5) — wrong for the
|
|
843
788
|
// Chinese-heavy zh-CN-hybrid KB. Values are the fastembed@2.x EmbeddingModel
|
|
@@ -847,7 +792,7 @@ var fabricConfigSchema = z6.object({
|
|
|
847
792
|
// available for full multilingual recall at a ~1GB download + slower CPU cost.
|
|
848
793
|
// (V1 research: fastembed@2.1.0 has NO multilingual-e5-SMALL — the originally
|
|
849
794
|
// planned pin — so bge-small-zh is the light Chinese choice.)
|
|
850
|
-
embed_model:
|
|
795
|
+
embed_model: z5.enum([
|
|
851
796
|
"fast-bge-small-zh-v1.5",
|
|
852
797
|
"fast-multilingual-e5-large",
|
|
853
798
|
"fast-bge-small-en-v1.5",
|
|
@@ -859,8 +804,8 @@ var fabricConfigSchema = z6.object({
|
|
|
859
804
|
});
|
|
860
805
|
|
|
861
806
|
// src/schemas/fabric-config-introspect.ts
|
|
862
|
-
import { z as
|
|
863
|
-
var positiveIntSchema =
|
|
807
|
+
import { z as z6 } from "zod";
|
|
808
|
+
var positiveIntSchema = z6.coerce.number().int().positive();
|
|
864
809
|
function makePositiveIntField(key, defaultValue) {
|
|
865
810
|
return {
|
|
866
811
|
key,
|
|
@@ -916,6 +861,28 @@ function makeEnumField(key, group, enumValues, defaultValue) {
|
|
|
916
861
|
}
|
|
917
862
|
};
|
|
918
863
|
}
|
|
864
|
+
function makeBooleanField(key, defaultValue) {
|
|
865
|
+
return {
|
|
866
|
+
key,
|
|
867
|
+
group: "D_behavior",
|
|
868
|
+
widget: "select",
|
|
869
|
+
label_i18n_key: `cli.config.fields.${key}.label`,
|
|
870
|
+
description_i18n_key: `cli.config.fields.${key}.description`,
|
|
871
|
+
default: String(defaultValue),
|
|
872
|
+
enum_values: ["true", "false"],
|
|
873
|
+
validate(raw) {
|
|
874
|
+
const trimmed = raw.trim();
|
|
875
|
+
if (trimmed === "true") return { ok: true, value: true };
|
|
876
|
+
if (trimmed === "false") return { ok: true, value: false };
|
|
877
|
+
return { ok: false, error: "Must be one of: true, false." };
|
|
878
|
+
},
|
|
879
|
+
format_for_display(value) {
|
|
880
|
+
if (typeof value === "boolean") return String(value);
|
|
881
|
+
if (value === void 0 || value === null) return String(defaultValue);
|
|
882
|
+
return String(value);
|
|
883
|
+
}
|
|
884
|
+
};
|
|
885
|
+
}
|
|
919
886
|
var SCHEMA_DEFAULTS = fabricConfigSchema.parse({});
|
|
920
887
|
function pickNumberDefault(key) {
|
|
921
888
|
const v = SCHEMA_DEFAULTS[key];
|
|
@@ -944,12 +911,13 @@ function getPanelFieldByKey(key) {
|
|
|
944
911
|
}
|
|
945
912
|
var PANEL_FIELDS = [
|
|
946
913
|
// --- Group A: Locale (2) ---
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
914
|
+
// grill-6fixes (D1): `fabric_language` is no longer a project-config field —
|
|
915
|
+
// it is the single machine-wide tone in `~/.fabric/fabric-global.json`. The
|
|
916
|
+
// panel still surfaces it (the `fabric config` language entry), but config.ts
|
|
917
|
+
// special-cases this key to read/write the GLOBAL config instead of the
|
|
918
|
+
// project file. Default is a literal "en" since there is no project-schema
|
|
919
|
+
// default to derive from.
|
|
920
|
+
makeEnumField("fabric_language", "A_locale", fabricLanguageSchema.options, "en"),
|
|
953
921
|
makeEnumField(
|
|
954
922
|
"default_layer_filter",
|
|
955
923
|
"A_locale",
|
|
@@ -993,39 +961,23 @@ var PANEL_FIELDS = [
|
|
|
993
961
|
"C_audit",
|
|
994
962
|
auditModeSchema.options,
|
|
995
963
|
AUDIT_MODE_PANEL_DEFAULT
|
|
996
|
-
)
|
|
964
|
+
),
|
|
965
|
+
// --- Group D: Behavior / features (2) ---
|
|
966
|
+
// nudge_mode — the master switch for the human-visible nudge experience
|
|
967
|
+
// (the most user-facing runtime knob, previously JSON-only). embed_enabled —
|
|
968
|
+
// vector semantic recall, panel-editable now that config lives in `.fabric`
|
|
969
|
+
// (A1); enabling also needs the host-side `fabric install --enable-embed`.
|
|
970
|
+
makeEnumField("nudge_mode", "D_behavior", nudgeModeSchema.options, "normal"),
|
|
971
|
+
makeBooleanField("embed_enabled", false)
|
|
997
972
|
];
|
|
998
973
|
|
|
999
|
-
// src/schemas/scope.ts
|
|
1000
|
-
import { z as z8 } from "zod";
|
|
1001
|
-
var PERSONAL_SCOPE = "personal";
|
|
1002
|
-
var KNOWN_SCOPE_PREFIXES = ["personal", "team", "project", "org"];
|
|
1003
|
-
var SCOPE_COORDINATE_PATTERN = /^[a-z0-9_-]+(:[a-z0-9_-]+)*$/u;
|
|
1004
|
-
var scopeCoordinateSchema = z8.string().min(1).regex(
|
|
1005
|
-
SCOPE_COORDINATE_PATTERN,
|
|
1006
|
-
"scope coordinate must be ':'-joined lowercase [a-z0-9_-] segments"
|
|
1007
|
-
);
|
|
1008
|
-
function scopeRoot(coordinate) {
|
|
1009
|
-
const colon = coordinate.indexOf(":");
|
|
1010
|
-
return colon === -1 ? coordinate : coordinate.slice(0, colon);
|
|
1011
|
-
}
|
|
1012
|
-
function isPersonalScope(coordinate) {
|
|
1013
|
-
return scopeRoot(coordinate) === PERSONAL_SCOPE;
|
|
1014
|
-
}
|
|
1015
|
-
var entryScopeMetadataSchema = z8.object({
|
|
1016
|
-
semantic_scope: scopeCoordinateSchema,
|
|
1017
|
-
// Store alias or UUID. Validated as a non-empty string here; the resolver
|
|
1018
|
-
// (P0.6) maps alias→UUID and verifies the store is in the read-set.
|
|
1019
|
-
visibility_store: z8.string().min(1)
|
|
1020
|
-
}).strict();
|
|
1021
|
-
|
|
1022
974
|
// src/schemas/store-stable-id.ts
|
|
1023
|
-
import { z as
|
|
975
|
+
import { z as z7 } from "zod";
|
|
1024
976
|
var localKnowledgeIdSchema = StableIdSchema;
|
|
1025
977
|
var UID_SEGMENT_PATTERN = /^[a-z0-9-]+$/u;
|
|
1026
|
-
var uidSchema =
|
|
978
|
+
var uidSchema = z7.string().min(1).regex(UID_SEGMENT_PATTERN, "uid must be lowercase [a-z0-9-] segments");
|
|
1027
979
|
var GLOBAL_REF_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(:[a-z0-9-]+)?:K[PT]-(MOD|DEC|GLD|PIT|PRO)-\d{4,}$/u;
|
|
1028
|
-
var globalRefSchema =
|
|
980
|
+
var globalRefSchema = z7.string().regex(GLOBAL_REF_PATTERN, "global_ref must be <store_uuid>[:<uid>]:<local_id>");
|
|
1029
981
|
function formatGlobalRef(parts) {
|
|
1030
982
|
const { store_uuid, uid, local_id } = parts;
|
|
1031
983
|
return uid === void 0 ? `${store_uuid}:${local_id}` : `${store_uuid}:${uid}:${local_id}`;
|
|
@@ -1050,14 +1002,14 @@ function parseGlobalRef(ref) {
|
|
|
1050
1002
|
local_id
|
|
1051
1003
|
};
|
|
1052
1004
|
}
|
|
1053
|
-
var storeKnowledgeTypeCountersSchema =
|
|
1054
|
-
MOD:
|
|
1055
|
-
DEC:
|
|
1056
|
-
GLD:
|
|
1057
|
-
PIT:
|
|
1058
|
-
PRO:
|
|
1005
|
+
var storeKnowledgeTypeCountersSchema = z7.object({
|
|
1006
|
+
MOD: z7.number().int().nonnegative().default(0),
|
|
1007
|
+
DEC: z7.number().int().nonnegative().default(0),
|
|
1008
|
+
GLD: z7.number().int().nonnegative().default(0),
|
|
1009
|
+
PIT: z7.number().int().nonnegative().default(0),
|
|
1010
|
+
PRO: z7.number().int().nonnegative().default(0)
|
|
1059
1011
|
}).default({ MOD: 0, DEC: 0, GLD: 0, PIT: 0, PRO: 0 });
|
|
1060
|
-
var storeCountersSchema =
|
|
1012
|
+
var storeCountersSchema = z7.object({
|
|
1061
1013
|
KP: storeKnowledgeTypeCountersSchema,
|
|
1062
1014
|
KT: storeKnowledgeTypeCountersSchema
|
|
1063
1015
|
}).default({
|
|
@@ -1066,64 +1018,63 @@ var storeCountersSchema = z9.object({
|
|
|
1066
1018
|
});
|
|
1067
1019
|
|
|
1068
1020
|
// src/schemas/parity-matrix.ts
|
|
1069
|
-
import { z as
|
|
1070
|
-
var PARITY_CLIENTS = ["claudeCode", "codexCLI"
|
|
1071
|
-
var parityClientSchema =
|
|
1021
|
+
import { z as z8 } from "zod";
|
|
1022
|
+
var PARITY_CLIENTS = ["claudeCode", "codexCLI"];
|
|
1023
|
+
var parityClientSchema = z8.enum(PARITY_CLIENTS);
|
|
1072
1024
|
var PARITY_SURFACES = ["skill", "hook", "mcp", "render"];
|
|
1073
|
-
var paritySurfaceSchema =
|
|
1074
|
-
var parityClientExpectationSchema =
|
|
1075
|
-
supported:
|
|
1076
|
-
mechanism:
|
|
1077
|
-
notes:
|
|
1025
|
+
var paritySurfaceSchema = z8.enum(PARITY_SURFACES);
|
|
1026
|
+
var parityClientExpectationSchema = z8.object({
|
|
1027
|
+
supported: z8.boolean(),
|
|
1028
|
+
mechanism: z8.string().optional(),
|
|
1029
|
+
notes: z8.string().optional()
|
|
1078
1030
|
}).strict();
|
|
1079
|
-
var parityCapabilitySchema =
|
|
1080
|
-
id:
|
|
1031
|
+
var parityCapabilitySchema = z8.object({
|
|
1032
|
+
id: z8.string().min(1),
|
|
1081
1033
|
surface: paritySurfaceSchema,
|
|
1082
|
-
description:
|
|
1083
|
-
clients:
|
|
1034
|
+
description: z8.string().min(1),
|
|
1035
|
+
clients: z8.object({
|
|
1084
1036
|
claudeCode: parityClientExpectationSchema,
|
|
1085
|
-
codexCLI: parityClientExpectationSchema
|
|
1086
|
-
cursor: parityClientExpectationSchema
|
|
1037
|
+
codexCLI: parityClientExpectationSchema
|
|
1087
1038
|
}).strict()
|
|
1088
1039
|
}).strict();
|
|
1089
|
-
var parityMatrixSchema =
|
|
1040
|
+
var parityMatrixSchema = z8.object({
|
|
1090
1041
|
// Schema/version tag of the matrix document itself.
|
|
1091
|
-
version:
|
|
1042
|
+
version: z8.string().min(1),
|
|
1092
1043
|
// Free-form note on what release/milestone this matrix targets.
|
|
1093
|
-
generated_for:
|
|
1094
|
-
capabilities:
|
|
1044
|
+
generated_for: z8.string().min(1),
|
|
1045
|
+
capabilities: z8.array(parityCapabilitySchema).min(1)
|
|
1095
1046
|
}).strict();
|
|
1096
1047
|
|
|
1097
1048
|
// src/resolver/contracts.ts
|
|
1098
|
-
import { z as
|
|
1049
|
+
import { z as z9 } from "zod";
|
|
1099
1050
|
var PROJECT_ROOT_SIGNALS = ["env", "marker", "cwd", "repo"];
|
|
1100
|
-
var projectRootSignalSchema =
|
|
1101
|
-
var projectRootSignalsSchema =
|
|
1051
|
+
var projectRootSignalSchema = z9.enum(PROJECT_ROOT_SIGNALS);
|
|
1052
|
+
var projectRootSignalsSchema = z9.object({
|
|
1102
1053
|
// FABRIC_PROJECT_ROOT, if set.
|
|
1103
|
-
env:
|
|
1054
|
+
env: z9.string().optional(),
|
|
1104
1055
|
// Nearest directory AT-OR-ABOVE cwd holding `.fabric/fabric-config.json`,
|
|
1105
1056
|
// if any (the upward marker search result; may equal cwd).
|
|
1106
|
-
markerDir:
|
|
1057
|
+
markerDir: z9.string().optional(),
|
|
1107
1058
|
// Always present — the process cwd.
|
|
1108
|
-
cwd:
|
|
1059
|
+
cwd: z9.string().min(1),
|
|
1109
1060
|
// git repo root, if inside a repo.
|
|
1110
|
-
repoRoot:
|
|
1061
|
+
repoRoot: z9.string().optional(),
|
|
1111
1062
|
// The `project_id` read from the winning root's fabric-config.json during
|
|
1112
1063
|
// (fs) signal collection. The pure resolver echoes it — it cannot invent a
|
|
1113
1064
|
// UUID. Worktrees of one repo share the committed config, hence the same
|
|
1114
1065
|
// project_id (S45 merge). Absent when no .fabric config exists at the root
|
|
1115
1066
|
// yet (fresh repo-fallback) → resolution still yields the root with a null
|
|
1116
1067
|
// projectId so the caller can mint+persist one at install time.
|
|
1117
|
-
discoveredProjectId:
|
|
1068
|
+
discoveredProjectId: z9.string().optional()
|
|
1118
1069
|
}).strict();
|
|
1119
|
-
var projectRootResolutionSchema =
|
|
1070
|
+
var projectRootResolutionSchema = z9.object({
|
|
1120
1071
|
// Absolute project root directory.
|
|
1121
|
-
projectRoot:
|
|
1072
|
+
projectRoot: z9.string().min(1),
|
|
1122
1073
|
// Stable project identity. One repo = one .fabric = one project_id (S32);
|
|
1123
1074
|
// git worktrees of the same repo resolve to the SAME project_id (S45).
|
|
1124
1075
|
// Null when the resolved root has no fabric-config.json yet (fresh
|
|
1125
1076
|
// repo-fallback) — the caller mints + persists a UUID at install time.
|
|
1126
|
-
projectId:
|
|
1077
|
+
projectId: z9.string().min(1).nullable(),
|
|
1127
1078
|
// Which signal won.
|
|
1128
1079
|
signalUsed: projectRootSignalSchema
|
|
1129
1080
|
}).strict();
|
|
@@ -1132,91 +1083,96 @@ var STORE_RESOLVER_WARNING_CODES = [
|
|
|
1132
1083
|
// required_stores entry has no matching mounted store (S51)
|
|
1133
1084
|
"local_only_no_remote",
|
|
1134
1085
|
// mounted but local-only (R5#5 nudge, non-fatal)
|
|
1135
|
-
"alias_unresolved"
|
|
1086
|
+
"alias_unresolved",
|
|
1136
1087
|
// referenced alias maps to no mounted store
|
|
1088
|
+
"missing_write_route"
|
|
1089
|
+
// multi/shared write requires an explicit route
|
|
1137
1090
|
];
|
|
1138
|
-
var storeResolverWarningCodeSchema =
|
|
1139
|
-
var storeResolverWarningSchema =
|
|
1091
|
+
var storeResolverWarningCodeSchema = z9.enum(STORE_RESOLVER_WARNING_CODES);
|
|
1092
|
+
var storeResolverWarningSchema = z9.object({
|
|
1140
1093
|
code: storeResolverWarningCodeSchema,
|
|
1141
1094
|
// The alias/UUID/id the warning concerns.
|
|
1142
|
-
ref:
|
|
1143
|
-
message:
|
|
1095
|
+
ref: z9.string().min(1),
|
|
1096
|
+
message: z9.string().min(1)
|
|
1144
1097
|
}).strict();
|
|
1145
|
-
var readSetEntrySchema =
|
|
1146
|
-
store_uuid:
|
|
1147
|
-
alias:
|
|
1148
|
-
remote:
|
|
1098
|
+
var readSetEntrySchema = z9.object({
|
|
1099
|
+
store_uuid: z9.string().min(1),
|
|
1100
|
+
alias: z9.string().min(1),
|
|
1101
|
+
remote: z9.string().min(1).optional(),
|
|
1149
1102
|
// Whether this store accepts writes from the current context. Personal
|
|
1150
1103
|
// store is writable; shared stores writable iff mounted with write intent.
|
|
1151
|
-
writable:
|
|
1104
|
+
writable: z9.boolean()
|
|
1152
1105
|
}).strict();
|
|
1153
|
-
var storeReadSetSchema =
|
|
1154
|
-
stores:
|
|
1155
|
-
warnings:
|
|
1106
|
+
var storeReadSetSchema = z9.object({
|
|
1107
|
+
stores: z9.array(readSetEntrySchema),
|
|
1108
|
+
warnings: z9.array(storeResolverWarningSchema)
|
|
1156
1109
|
}).strict();
|
|
1157
|
-
var writeTargetSchema =
|
|
1158
|
-
store_uuid:
|
|
1159
|
-
alias:
|
|
1110
|
+
var writeTargetSchema = z9.object({
|
|
1111
|
+
store_uuid: z9.string().min(1),
|
|
1112
|
+
alias: z9.string().min(1)
|
|
1160
1113
|
}).strict();
|
|
1161
|
-
var storeResolveInputSchema =
|
|
1114
|
+
var storeResolveInputSchema = z9.object({
|
|
1162
1115
|
// Machine identity (S33) — namespaces personal ids; identifies personal store.
|
|
1163
|
-
uid:
|
|
1116
|
+
uid: z9.string().min(1),
|
|
1164
1117
|
// Stores mounted on this machine (from global config).
|
|
1165
|
-
mountedStores:
|
|
1166
|
-
|
|
1167
|
-
store_uuid:
|
|
1168
|
-
alias:
|
|
1169
|
-
|
|
1170
|
-
|
|
1118
|
+
mountedStores: z9.array(
|
|
1119
|
+
z9.object({
|
|
1120
|
+
store_uuid: z9.string().min(1),
|
|
1121
|
+
alias: z9.string().min(1),
|
|
1122
|
+
mount_name: z9.string().min(1).optional(),
|
|
1123
|
+
remote: z9.string().min(1).optional(),
|
|
1124
|
+
writable: z9.boolean().default(true),
|
|
1171
1125
|
// Marks the implicit personal store.
|
|
1172
|
-
personal:
|
|
1126
|
+
personal: z9.boolean().default(false)
|
|
1173
1127
|
}).strict()
|
|
1174
1128
|
),
|
|
1175
1129
|
// The project's declared required_stores (ids/aliases + optional remote).
|
|
1176
|
-
requiredStores:
|
|
1177
|
-
|
|
1178
|
-
id:
|
|
1179
|
-
suggested_remote:
|
|
1130
|
+
requiredStores: z9.array(
|
|
1131
|
+
z9.object({
|
|
1132
|
+
id: z9.string().min(1),
|
|
1133
|
+
suggested_remote: z9.string().min(1).optional()
|
|
1180
1134
|
}).strict()
|
|
1181
1135
|
),
|
|
1182
1136
|
// Alias selected as the active write store for non-personal scopes, if any.
|
|
1183
|
-
activeWriteAlias:
|
|
1137
|
+
activeWriteAlias: z9.string().min(1).optional(),
|
|
1138
|
+
// Scope-aware write routes. Exact scope wins first, then longest prefix route.
|
|
1139
|
+
writeRoutes: z9.array(
|
|
1140
|
+
z9.object({
|
|
1141
|
+
scope: z9.string().min(1),
|
|
1142
|
+
store: z9.string().min(1)
|
|
1143
|
+
}).strict()
|
|
1144
|
+
).optional().default([]),
|
|
1145
|
+
defaultWriteAlias: z9.string().min(1).optional()
|
|
1184
1146
|
}).strict();
|
|
1185
|
-
var projectRootGoldenCaseSchema =
|
|
1186
|
-
name:
|
|
1187
|
-
note:
|
|
1147
|
+
var projectRootGoldenCaseSchema = z9.object({
|
|
1148
|
+
name: z9.string().min(1),
|
|
1149
|
+
note: z9.string().optional(),
|
|
1188
1150
|
signals: projectRootSignalsSchema,
|
|
1189
1151
|
// null expected = resolver should return no root for these signals.
|
|
1190
1152
|
expected: projectRootResolutionSchema.nullable()
|
|
1191
1153
|
}).strict();
|
|
1192
|
-
var projectRootGoldenFileSchema =
|
|
1193
|
-
contract:
|
|
1194
|
-
cases:
|
|
1154
|
+
var projectRootGoldenFileSchema = z9.object({
|
|
1155
|
+
contract: z9.literal("project-root.golden"),
|
|
1156
|
+
cases: z9.array(projectRootGoldenCaseSchema).min(1)
|
|
1195
1157
|
}).strict();
|
|
1196
|
-
var readSetGoldenCaseSchema =
|
|
1197
|
-
name:
|
|
1198
|
-
note:
|
|
1158
|
+
var readSetGoldenCaseSchema = z9.object({
|
|
1159
|
+
name: z9.string().min(1),
|
|
1160
|
+
note: z9.string().optional(),
|
|
1199
1161
|
input: storeResolveInputSchema,
|
|
1200
1162
|
// Scope under test for the write-target expectation.
|
|
1201
|
-
writeScope:
|
|
1202
|
-
expected:
|
|
1163
|
+
writeScope: z9.string().min(1),
|
|
1164
|
+
expected: z9.object({
|
|
1203
1165
|
readSet: storeReadSetSchema,
|
|
1204
1166
|
writeTarget: writeTargetSchema.nullable(),
|
|
1205
|
-
writeWarnings:
|
|
1167
|
+
writeWarnings: z9.array(storeResolverWarningSchema)
|
|
1206
1168
|
}).strict()
|
|
1207
1169
|
}).strict();
|
|
1208
|
-
var readSetGoldenFileSchema =
|
|
1209
|
-
contract:
|
|
1210
|
-
cases:
|
|
1170
|
+
var readSetGoldenFileSchema = z9.object({
|
|
1171
|
+
contract: z9.literal("read-set.golden"),
|
|
1172
|
+
cases: z9.array(readSetGoldenCaseSchema).min(1)
|
|
1211
1173
|
}).strict();
|
|
1212
1174
|
|
|
1213
1175
|
// src/resolver/project-root-resolver.ts
|
|
1214
|
-
var ResolverNotImplementedError = class extends Error {
|
|
1215
|
-
constructor(what) {
|
|
1216
|
-
super(`${what} is not implemented yet (TDD target)`);
|
|
1217
|
-
this.name = "ResolverNotImplementedError";
|
|
1218
|
-
}
|
|
1219
|
-
};
|
|
1220
1176
|
function createProjectRootResolver() {
|
|
1221
1177
|
return {
|
|
1222
1178
|
resolve(signals) {
|
|
@@ -1254,12 +1210,65 @@ function personalEntry(input) {
|
|
|
1254
1210
|
}
|
|
1255
1211
|
return entry;
|
|
1256
1212
|
}
|
|
1213
|
+
function readSetEntryFromMounted(store) {
|
|
1214
|
+
const entry = {
|
|
1215
|
+
store_uuid: store.store_uuid,
|
|
1216
|
+
alias: store.alias,
|
|
1217
|
+
writable: store.writable
|
|
1218
|
+
};
|
|
1219
|
+
if (store.remote !== void 0) {
|
|
1220
|
+
entry.remote = store.remote;
|
|
1221
|
+
return { entry };
|
|
1222
|
+
}
|
|
1223
|
+
return {
|
|
1224
|
+
entry,
|
|
1225
|
+
warning: {
|
|
1226
|
+
code: "local_only_no_remote",
|
|
1227
|
+
ref: store.alias,
|
|
1228
|
+
message: `store '${store.alias}' is local-only; add a git remote to back it up (\`fabric store ... \` / doctor nudge)`
|
|
1229
|
+
}
|
|
1230
|
+
};
|
|
1231
|
+
}
|
|
1232
|
+
function isMountedPersonal(input, storeUuid) {
|
|
1233
|
+
return input.mountedStores.some((store) => store.store_uuid === storeUuid && store.personal);
|
|
1234
|
+
}
|
|
1235
|
+
function routeMatches(routeScope, scope) {
|
|
1236
|
+
return scope === routeScope || scope.startsWith(`${routeScope}:`);
|
|
1237
|
+
}
|
|
1238
|
+
function resolveRouteAlias(input, scope) {
|
|
1239
|
+
const routes = input.writeRoutes ?? [];
|
|
1240
|
+
const exact = routes.find((route) => route.scope === scope);
|
|
1241
|
+
if (exact !== void 0) {
|
|
1242
|
+
return exact.store;
|
|
1243
|
+
}
|
|
1244
|
+
const prefix = routes.filter((route) => routeMatches(route.scope, scope)).sort((a, b) => b.scope.length - a.scope.length)[0];
|
|
1245
|
+
return prefix?.store ?? input.defaultWriteAlias ?? input.activeWriteAlias;
|
|
1246
|
+
}
|
|
1247
|
+
function hasMultipleSharedStores(input, readSet) {
|
|
1248
|
+
return readSet.stores.filter((store) => !isMountedPersonal(input, store.store_uuid)).length > 1;
|
|
1249
|
+
}
|
|
1250
|
+
function hasExplicitRouteOrDefault(input, scope) {
|
|
1251
|
+
const routes = input.writeRoutes ?? [];
|
|
1252
|
+
return routes.some((route) => routeMatches(route.scope, scope)) || input.defaultWriteAlias !== void 0;
|
|
1253
|
+
}
|
|
1257
1254
|
function createStoreResolver() {
|
|
1258
1255
|
return {
|
|
1259
1256
|
resolveReadSet(input) {
|
|
1260
1257
|
const stores = [];
|
|
1261
1258
|
const warnings = [];
|
|
1259
|
+
const seenStoreUuids = /* @__PURE__ */ new Set();
|
|
1262
1260
|
for (const req of input.requiredStores) {
|
|
1261
|
+
if (req.suggested_remote === "$personal") {
|
|
1262
|
+
const personal2 = findPersonal(input);
|
|
1263
|
+
if (personal2 === void 0) {
|
|
1264
|
+
warnings.push({
|
|
1265
|
+
code: "missing_store",
|
|
1266
|
+
ref: req.id,
|
|
1267
|
+
message: `required store '${req.id}' is not mounted; run \`fabric store add\` (suggested remote: $personal)`
|
|
1268
|
+
});
|
|
1269
|
+
}
|
|
1270
|
+
continue;
|
|
1271
|
+
}
|
|
1263
1272
|
const matched = input.mountedStores.find(
|
|
1264
1273
|
(m) => !m.personal && (m.alias === req.id || m.store_uuid === req.id)
|
|
1265
1274
|
);
|
|
@@ -1272,25 +1281,20 @@ function createStoreResolver() {
|
|
|
1272
1281
|
});
|
|
1273
1282
|
continue;
|
|
1274
1283
|
}
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
entry.remote = matched.remote;
|
|
1282
|
-
} else {
|
|
1283
|
-
warnings.push({
|
|
1284
|
-
code: "local_only_no_remote",
|
|
1285
|
-
ref: matched.alias,
|
|
1286
|
-
message: `store '${matched.alias}' is local-only; add a git remote to back it up (\`fabric store ... \` / doctor nudge)`
|
|
1287
|
-
});
|
|
1284
|
+
if (seenStoreUuids.has(matched.store_uuid)) {
|
|
1285
|
+
continue;
|
|
1286
|
+
}
|
|
1287
|
+
const { entry, warning } = readSetEntryFromMounted(matched);
|
|
1288
|
+
if (warning !== void 0) {
|
|
1289
|
+
warnings.push(warning);
|
|
1288
1290
|
}
|
|
1289
1291
|
stores.push(entry);
|
|
1292
|
+
seenStoreUuids.add(matched.store_uuid);
|
|
1290
1293
|
}
|
|
1291
1294
|
const personal = personalEntry(input);
|
|
1292
|
-
if (personal !== void 0) {
|
|
1295
|
+
if (personal !== void 0 && !seenStoreUuids.has(personal.store_uuid)) {
|
|
1293
1296
|
stores.push(personal);
|
|
1297
|
+
seenStoreUuids.add(personal.store_uuid);
|
|
1294
1298
|
}
|
|
1295
1299
|
return { stores, warnings };
|
|
1296
1300
|
},
|
|
@@ -1311,15 +1315,31 @@ function createStoreResolver() {
|
|
|
1311
1315
|
}
|
|
1312
1316
|
return { target: { store_uuid: p.store_uuid, alias: p.alias }, warnings: [] };
|
|
1313
1317
|
}
|
|
1314
|
-
const
|
|
1318
|
+
const readSet = this.resolveReadSet(input);
|
|
1319
|
+
if (hasMultipleSharedStores(input, readSet) && !hasExplicitRouteOrDefault(input, scope)) {
|
|
1320
|
+
return {
|
|
1321
|
+
target: null,
|
|
1322
|
+
warnings: [
|
|
1323
|
+
{
|
|
1324
|
+
code: "missing_write_route",
|
|
1325
|
+
ref: scope,
|
|
1326
|
+
message: `scope '${scope}' has no explicit write route; set \`fabric store route-write ${scope} <alias>\``
|
|
1327
|
+
}
|
|
1328
|
+
]
|
|
1329
|
+
};
|
|
1330
|
+
}
|
|
1331
|
+
const routeAlias = resolveRouteAlias(input, scope);
|
|
1332
|
+
const active = routeAlias === void 0 ? void 0 : readSet.stores.find(
|
|
1333
|
+
(store) => store.writable && !isMountedPersonal(input, store.store_uuid) && (store.alias === routeAlias || store.store_uuid === routeAlias)
|
|
1334
|
+
);
|
|
1315
1335
|
if (active === void 0) {
|
|
1316
1336
|
return {
|
|
1317
1337
|
target: null,
|
|
1318
1338
|
warnings: [
|
|
1319
1339
|
{
|
|
1320
1340
|
code: "alias_unresolved",
|
|
1321
|
-
ref:
|
|
1322
|
-
message: `no writable store for scope '${scope}'; set
|
|
1341
|
+
ref: routeAlias ?? scope,
|
|
1342
|
+
message: `no writable store for scope '${scope}'; set a write route or default write store`
|
|
1323
1343
|
}
|
|
1324
1344
|
]
|
|
1325
1345
|
};
|
|
@@ -1333,7 +1353,8 @@ function createStoreResolver() {
|
|
|
1333
1353
|
}
|
|
1334
1354
|
|
|
1335
1355
|
// src/resolver/store-disk-reader.ts
|
|
1336
|
-
import { existsSync, readdirSync, readFileSync
|
|
1356
|
+
import { existsSync, lstatSync, readdirSync, readFileSync } from "fs";
|
|
1357
|
+
import { readFile } from "fs/promises";
|
|
1337
1358
|
import { join } from "path";
|
|
1338
1359
|
function readStoreIdentity(absDir) {
|
|
1339
1360
|
const identityFile = join(absDir, STORE_LAYOUT.identityFile);
|
|
@@ -1349,6 +1370,17 @@ function readStoreIdentity(absDir) {
|
|
|
1349
1370
|
const parsed = storeIdentitySchema.safeParse(raw);
|
|
1350
1371
|
return parsed.success ? parsed.data : null;
|
|
1351
1372
|
}
|
|
1373
|
+
async function readStoreIdentityAsync(absDir) {
|
|
1374
|
+
const identityFile = join(absDir, STORE_LAYOUT.identityFile);
|
|
1375
|
+
let raw;
|
|
1376
|
+
try {
|
|
1377
|
+
raw = JSON.parse(await readFile(identityFile, "utf8"));
|
|
1378
|
+
} catch {
|
|
1379
|
+
return null;
|
|
1380
|
+
}
|
|
1381
|
+
const parsed = storeIdentitySchema.safeParse(raw);
|
|
1382
|
+
return parsed.success ? parsed.data : null;
|
|
1383
|
+
}
|
|
1352
1384
|
function recognizeStoreDir(absDir) {
|
|
1353
1385
|
return readStoreIdentity(absDir) !== null;
|
|
1354
1386
|
}
|
|
@@ -1408,10 +1440,14 @@ function findStoreExecutableViolations(absDir, options = {}) {
|
|
|
1408
1440
|
const relPath = rel === "" ? entry : `${rel}/${entry}`;
|
|
1409
1441
|
let stat;
|
|
1410
1442
|
try {
|
|
1411
|
-
stat =
|
|
1443
|
+
stat = lstatSync(abs);
|
|
1412
1444
|
} catch {
|
|
1413
1445
|
continue;
|
|
1414
1446
|
}
|
|
1447
|
+
if (stat.isSymbolicLink()) {
|
|
1448
|
+
violations.push(relPath);
|
|
1449
|
+
continue;
|
|
1450
|
+
}
|
|
1415
1451
|
if (stat.isDirectory()) {
|
|
1416
1452
|
walk(abs, relPath, depth + 1);
|
|
1417
1453
|
continue;
|
|
@@ -1525,9 +1561,10 @@ function resolveCandidates(candidates, options = {}) {
|
|
|
1525
1561
|
}
|
|
1526
1562
|
|
|
1527
1563
|
// src/store/core.ts
|
|
1528
|
-
import {
|
|
1529
|
-
import {
|
|
1564
|
+
import { execFile } from "child_process";
|
|
1565
|
+
import { access, mkdir, readdir, readFile as readFile2, writeFile } from "fs/promises";
|
|
1530
1566
|
import { join as join2 } from "path";
|
|
1567
|
+
import { promisify } from "util";
|
|
1531
1568
|
var STORE_PENDING_DIR = "pending";
|
|
1532
1569
|
var STORE_GITIGNORE = [
|
|
1533
1570
|
"# v2.1 store \u2014 volatile / derived data is never committed",
|
|
@@ -1536,96 +1573,106 @@ var STORE_GITIGNORE = [
|
|
|
1536
1573
|
".cache/",
|
|
1537
1574
|
""
|
|
1538
1575
|
].join("\n");
|
|
1539
|
-
|
|
1540
|
-
|
|
1576
|
+
var execFileAsync = promisify(execFile);
|
|
1577
|
+
async function git(cwd, args) {
|
|
1578
|
+
await execFileAsync("git", args, { cwd });
|
|
1541
1579
|
}
|
|
1542
|
-
function initStore(absDir, identity, options = {}) {
|
|
1580
|
+
async function initStore(absDir, identity, options = {}) {
|
|
1543
1581
|
const parsed = storeIdentitySchema.parse(identity);
|
|
1544
1582
|
const identityFile = join2(absDir, STORE_LAYOUT.identityFile);
|
|
1545
|
-
|
|
1583
|
+
try {
|
|
1584
|
+
await access(identityFile);
|
|
1546
1585
|
throw new Error(`store already initialized at ${absDir} (store.json exists)`);
|
|
1586
|
+
} catch (err) {
|
|
1587
|
+
if (err instanceof Error && err.message.includes("already initialized")) {
|
|
1588
|
+
throw err;
|
|
1589
|
+
}
|
|
1547
1590
|
}
|
|
1548
1591
|
for (const type of STORE_KNOWLEDGE_TYPE_DIRS) {
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1592
|
+
const typeDir = join2(absDir, STORE_LAYOUT.knowledgeDir, type);
|
|
1593
|
+
await mkdir(typeDir, { recursive: true });
|
|
1594
|
+
await writeFile(join2(typeDir, ".gitkeep"), "", "utf8");
|
|
1595
|
+
}
|
|
1596
|
+
await mkdir(join2(absDir, STORE_LAYOUT.knowledgeDir, STORE_PENDING_DIR), { recursive: true });
|
|
1597
|
+
await mkdir(join2(absDir, STORE_LAYOUT.bindingsDir), { recursive: true });
|
|
1598
|
+
await mkdir(join2(absDir, STORE_LAYOUT.stateDir), { recursive: true });
|
|
1599
|
+
await writeFile(identityFile, `${JSON.stringify(parsed, null, 2)}
|
|
1555
1600
|
`, "utf8");
|
|
1556
|
-
|
|
1601
|
+
await writeFile(join2(absDir, ".gitignore"), STORE_GITIGNORE, "utf8");
|
|
1557
1602
|
if (options.git !== false) {
|
|
1558
|
-
git(absDir, ["init", "-b", "main"]);
|
|
1603
|
+
await git(absDir, ["init", "-b", "main"]);
|
|
1559
1604
|
}
|
|
1560
|
-
const readBack =
|
|
1605
|
+
const readBack = await readStoreIdentityAsync(absDir);
|
|
1561
1606
|
if (readBack === null) {
|
|
1562
1607
|
throw new Error(`store init wrote an unrecognizable store.json at ${absDir}`);
|
|
1563
1608
|
}
|
|
1564
1609
|
return readBack;
|
|
1565
1610
|
}
|
|
1566
|
-
function listMarkdown(dir) {
|
|
1567
|
-
|
|
1611
|
+
async function listMarkdown(dir) {
|
|
1612
|
+
let entries;
|
|
1613
|
+
try {
|
|
1614
|
+
entries = await readdir(dir);
|
|
1615
|
+
} catch {
|
|
1568
1616
|
return [];
|
|
1569
1617
|
}
|
|
1570
|
-
return
|
|
1618
|
+
return entries.filter((name) => name.endsWith(".md")).sort().map((name) => join2(dir, name));
|
|
1571
1619
|
}
|
|
1572
|
-
function listStoreKnowledge(store) {
|
|
1620
|
+
async function listStoreKnowledge(store) {
|
|
1573
1621
|
const refs = [];
|
|
1574
1622
|
for (const type of STORE_KNOWLEDGE_TYPE_DIRS) {
|
|
1575
|
-
for (const file of listMarkdown(join2(store.dir, STORE_LAYOUT.knowledgeDir, type))) {
|
|
1623
|
+
for (const file of await listMarkdown(join2(store.dir, STORE_LAYOUT.knowledgeDir, type))) {
|
|
1576
1624
|
refs.push({ store_uuid: store.store_uuid, alias: store.alias, type, file });
|
|
1577
1625
|
}
|
|
1578
1626
|
}
|
|
1579
1627
|
return refs;
|
|
1580
1628
|
}
|
|
1581
|
-
function readKnowledgeAcrossStores(stores) {
|
|
1582
|
-
|
|
1629
|
+
async function readKnowledgeAcrossStores(stores) {
|
|
1630
|
+
const lists = await Promise.all(stores.map((store) => listStoreKnowledge(store)));
|
|
1631
|
+
return lists.flat();
|
|
1583
1632
|
}
|
|
1584
1633
|
function storeProjectsPath(storeDir) {
|
|
1585
1634
|
return join2(storeDir, STORE_LAYOUT.projectsFile);
|
|
1586
1635
|
}
|
|
1587
|
-
function readStoreProjects(storeDir) {
|
|
1636
|
+
async function readStoreProjects(storeDir) {
|
|
1588
1637
|
const path = storeProjectsPath(storeDir);
|
|
1589
|
-
if (!existsSync2(path)) {
|
|
1590
|
-
return [];
|
|
1591
|
-
}
|
|
1592
1638
|
let raw;
|
|
1593
1639
|
try {
|
|
1594
|
-
raw = JSON.parse(
|
|
1640
|
+
raw = JSON.parse(await readFile2(path, "utf8"));
|
|
1595
1641
|
} catch {
|
|
1596
1642
|
return [];
|
|
1597
1643
|
}
|
|
1598
1644
|
const parsed = storeProjectsFileSchema.safeParse(raw);
|
|
1599
1645
|
return parsed.success ? parsed.data.projects : [];
|
|
1600
1646
|
}
|
|
1601
|
-
function storeHasProject(storeDir, id) {
|
|
1602
|
-
return readStoreProjects(storeDir).some((p) => p.id === id);
|
|
1647
|
+
async function storeHasProject(storeDir, id) {
|
|
1648
|
+
return (await readStoreProjects(storeDir)).some((p) => p.id === id);
|
|
1603
1649
|
}
|
|
1604
|
-
function addStoreProject(storeDir, project) {
|
|
1650
|
+
async function addStoreProject(storeDir, project) {
|
|
1605
1651
|
const parsed = storeProjectSchema.parse(project);
|
|
1606
|
-
const existing = readStoreProjects(storeDir);
|
|
1652
|
+
const existing = await readStoreProjects(storeDir);
|
|
1607
1653
|
if (existing.some((p) => p.id === parsed.id)) {
|
|
1608
1654
|
throw new Error(`project '${parsed.id}' already exists in store at ${storeDir}`);
|
|
1609
1655
|
}
|
|
1610
1656
|
const next = [...existing, parsed];
|
|
1611
1657
|
const validated = storeProjectsFileSchema.parse({ projects: next });
|
|
1612
|
-
|
|
1658
|
+
await writeFile(storeProjectsPath(storeDir), `${JSON.stringify(validated, null, 2)}
|
|
1613
1659
|
`, "utf8");
|
|
1614
1660
|
return validated.projects;
|
|
1615
1661
|
}
|
|
1616
|
-
function aggregatePendingAcrossStores(stores) {
|
|
1617
|
-
|
|
1618
|
-
(store) => listMarkdown(join2(store.dir, STORE_LAYOUT.knowledgeDir, STORE_PENDING_DIR)).map((file) => ({
|
|
1662
|
+
async function aggregatePendingAcrossStores(stores) {
|
|
1663
|
+
const lists = await Promise.all(stores.map(
|
|
1664
|
+
async (store) => (await listMarkdown(join2(store.dir, STORE_LAYOUT.knowledgeDir, STORE_PENDING_DIR))).map((file) => ({
|
|
1619
1665
|
store_uuid: store.store_uuid,
|
|
1620
1666
|
alias: store.alias,
|
|
1621
1667
|
type: STORE_PENDING_DIR,
|
|
1622
1668
|
file
|
|
1623
1669
|
}))
|
|
1624
|
-
);
|
|
1670
|
+
));
|
|
1671
|
+
return lists.flat();
|
|
1625
1672
|
}
|
|
1626
1673
|
|
|
1627
1674
|
// src/store/store-counters.ts
|
|
1628
|
-
import { existsSync as
|
|
1675
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, readdirSync as readdirSync2, writeFileSync } from "fs";
|
|
1629
1676
|
import { join as join3 } from "path";
|
|
1630
1677
|
function storeCountersPath(storeDir) {
|
|
1631
1678
|
return join3(storeDir, STORE_LAYOUT.countersFile);
|
|
@@ -1633,7 +1680,7 @@ function storeCountersPath(storeDir) {
|
|
|
1633
1680
|
function readStoreCounters(storeDir) {
|
|
1634
1681
|
let raw;
|
|
1635
1682
|
try {
|
|
1636
|
-
raw =
|
|
1683
|
+
raw = readFileSync2(storeCountersPath(storeDir), "utf8");
|
|
1637
1684
|
} catch {
|
|
1638
1685
|
return defaultAgentsMetaCounters();
|
|
1639
1686
|
}
|
|
@@ -1646,10 +1693,39 @@ function readStoreCounters(storeDir) {
|
|
|
1646
1693
|
const result = AgentsMetaCountersSchema.safeParse(parsed);
|
|
1647
1694
|
return result.success ? result.data : defaultAgentsMetaCounters();
|
|
1648
1695
|
}
|
|
1696
|
+
function preserveCorruptCounters(path, raw) {
|
|
1697
|
+
const corruptedPath = `${path}.corrupted.${Date.now()}`;
|
|
1698
|
+
writeFileSync(corruptedPath, raw, "utf8");
|
|
1699
|
+
return corruptedPath;
|
|
1700
|
+
}
|
|
1701
|
+
function readStoreCountersForAllocation(storeDir) {
|
|
1702
|
+
const path = storeCountersPath(storeDir);
|
|
1703
|
+
if (!existsSync2(path)) {
|
|
1704
|
+
return defaultAgentsMetaCounters();
|
|
1705
|
+
}
|
|
1706
|
+
const raw = readFileSync2(path, "utf8");
|
|
1707
|
+
let parsed;
|
|
1708
|
+
try {
|
|
1709
|
+
parsed = JSON.parse(raw);
|
|
1710
|
+
} catch (error) {
|
|
1711
|
+
const corruptedPath = preserveCorruptCounters(path, raw);
|
|
1712
|
+
throw new Error(
|
|
1713
|
+
`store counters.json is corrupt; forensic copy saved to ${corruptedPath}. Run doctor --fix or reconcileStoreCounters before allocating a new stable_id. Parse error: ${error instanceof Error ? error.message : String(error)}`
|
|
1714
|
+
);
|
|
1715
|
+
}
|
|
1716
|
+
const result = AgentsMetaCountersSchema.safeParse(parsed);
|
|
1717
|
+
if (!result.success) {
|
|
1718
|
+
const corruptedPath = preserveCorruptCounters(path, raw);
|
|
1719
|
+
throw new Error(
|
|
1720
|
+
`store counters.json is schema-invalid; forensic copy saved to ${corruptedPath}. Run doctor --fix or reconcileStoreCounters before allocating a new stable_id.`
|
|
1721
|
+
);
|
|
1722
|
+
}
|
|
1723
|
+
return result.data;
|
|
1724
|
+
}
|
|
1649
1725
|
async function allocateStoreKnowledgeId(layer, type, storeDir) {
|
|
1650
1726
|
const countersPath = storeCountersPath(storeDir);
|
|
1651
1727
|
return withFileLock(`${countersPath}.lock`, async () => {
|
|
1652
|
-
const counters =
|
|
1728
|
+
const counters = readStoreCountersForAllocation(storeDir);
|
|
1653
1729
|
const { id, nextCounters } = allocateKnowledgeId(layer, type, counters);
|
|
1654
1730
|
await atomicWriteJson(countersPath, nextCounters, { indent: 2 });
|
|
1655
1731
|
return id;
|
|
@@ -1658,7 +1734,7 @@ async function allocateStoreKnowledgeId(layer, type, storeDir) {
|
|
|
1658
1734
|
function readEntryId(file) {
|
|
1659
1735
|
let content;
|
|
1660
1736
|
try {
|
|
1661
|
-
content =
|
|
1737
|
+
content = readFileSync2(file, "utf8");
|
|
1662
1738
|
} catch {
|
|
1663
1739
|
return null;
|
|
1664
1740
|
}
|
|
@@ -1678,10 +1754,10 @@ function reconcileStoreCounters(storeDir) {
|
|
|
1678
1754
|
};
|
|
1679
1755
|
for (const type of STORE_KNOWLEDGE_TYPE_DIRS) {
|
|
1680
1756
|
const dir = join3(storeDir, STORE_LAYOUT.knowledgeDir, type);
|
|
1681
|
-
if (!
|
|
1757
|
+
if (!existsSync2(dir)) {
|
|
1682
1758
|
continue;
|
|
1683
1759
|
}
|
|
1684
|
-
for (const name of
|
|
1760
|
+
for (const name of readdirSync2(dir)) {
|
|
1685
1761
|
if (!name.endsWith(".md")) {
|
|
1686
1762
|
continue;
|
|
1687
1763
|
}
|
|
@@ -1694,52 +1770,28 @@ function reconcileStoreCounters(storeDir) {
|
|
|
1694
1770
|
next[layerKey][typeCode] = Math.max(next[layerKey][typeCode], parsed.counter);
|
|
1695
1771
|
}
|
|
1696
1772
|
}
|
|
1697
|
-
|
|
1773
|
+
writeFileSync(storeCountersPath(storeDir), `${JSON.stringify(next, null, 2)}
|
|
1698
1774
|
`, "utf8");
|
|
1699
1775
|
return next;
|
|
1700
1776
|
}
|
|
1701
1777
|
|
|
1702
|
-
// src/store/global-config-io.ts
|
|
1703
|
-
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
1704
|
-
import { homedir } from "os";
|
|
1705
|
-
import { join as join4 } from "path";
|
|
1706
|
-
function resolveGlobalRoot() {
|
|
1707
|
-
return join4(process.env.FABRIC_HOME ?? homedir(), ".fabric");
|
|
1708
|
-
}
|
|
1709
|
-
function globalConfigPath(globalRoot = resolveGlobalRoot()) {
|
|
1710
|
-
return join4(globalRoot, "fabric-global.json");
|
|
1711
|
-
}
|
|
1712
|
-
function loadGlobalConfig(globalRoot = resolveGlobalRoot()) {
|
|
1713
|
-
const path = globalConfigPath(globalRoot);
|
|
1714
|
-
if (!existsSync4(path)) {
|
|
1715
|
-
return null;
|
|
1716
|
-
}
|
|
1717
|
-
return globalConfigSchema.parse(JSON.parse(readFileSync4(path, "utf8")));
|
|
1718
|
-
}
|
|
1719
|
-
function saveGlobalConfig(config, globalRoot = resolveGlobalRoot()) {
|
|
1720
|
-
const validated = globalConfigSchema.parse(config);
|
|
1721
|
-
mkdirSync2(globalRoot, { recursive: true });
|
|
1722
|
-
writeFileSync3(globalConfigPath(globalRoot), `${JSON.stringify(validated, null, 2)}
|
|
1723
|
-
`, "utf8");
|
|
1724
|
-
}
|
|
1725
|
-
|
|
1726
1778
|
// src/store/project-config-io.ts
|
|
1727
|
-
import { existsSync as
|
|
1728
|
-
import { join as
|
|
1779
|
+
import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
1780
|
+
import { join as join4 } from "path";
|
|
1729
1781
|
function projectConfigPath(projectRoot) {
|
|
1730
|
-
return
|
|
1782
|
+
return join4(projectRoot, ".fabric", "fabric-config.json");
|
|
1731
1783
|
}
|
|
1732
1784
|
function loadProjectConfig(projectRoot) {
|
|
1733
1785
|
const path = projectConfigPath(projectRoot);
|
|
1734
|
-
if (!
|
|
1786
|
+
if (!existsSync3(path)) {
|
|
1735
1787
|
return null;
|
|
1736
1788
|
}
|
|
1737
|
-
return fabricConfigSchema.parse(JSON.parse(
|
|
1789
|
+
return fabricConfigSchema.parse(JSON.parse(readFileSync3(path, "utf8")));
|
|
1738
1790
|
}
|
|
1739
1791
|
function saveProjectConfig(config, projectRoot) {
|
|
1740
1792
|
const validated = fabricConfigSchema.parse(config);
|
|
1741
|
-
|
|
1742
|
-
|
|
1793
|
+
mkdirSync(join4(projectRoot, ".fabric"), { recursive: true });
|
|
1794
|
+
writeFileSync2(projectConfigPath(projectRoot), `${JSON.stringify(validated, null, 2)}
|
|
1743
1795
|
`, "utf8");
|
|
1744
1796
|
}
|
|
1745
1797
|
|
|
@@ -1755,6 +1807,7 @@ function buildStoreResolveInput(projectRoot, globalRoot = resolveGlobalRoot()) {
|
|
|
1755
1807
|
mountedStores: global.stores.map((s) => ({
|
|
1756
1808
|
store_uuid: s.store_uuid,
|
|
1757
1809
|
alias: s.alias,
|
|
1810
|
+
...s.mount_name === void 0 ? {} : { mount_name: s.mount_name },
|
|
1758
1811
|
...s.remote === void 0 ? {} : { remote: s.remote },
|
|
1759
1812
|
writable: s.writable ?? true,
|
|
1760
1813
|
personal: s.personal ?? false
|
|
@@ -1765,22 +1818,43 @@ function buildStoreResolveInput(projectRoot, globalRoot = resolveGlobalRoot()) {
|
|
|
1765
1818
|
...r.suggested_remote === void 0 ? {} : { suggested_remote: r.suggested_remote }
|
|
1766
1819
|
})
|
|
1767
1820
|
),
|
|
1768
|
-
...project?.active_write_store === void 0 ? {} : { activeWriteAlias: project.active_write_store }
|
|
1821
|
+
...project?.active_write_store === void 0 ? {} : { activeWriteAlias: project.active_write_store },
|
|
1822
|
+
writeRoutes: project?.write_routes ?? [],
|
|
1823
|
+
...project?.default_write_store === void 0 ? {} : { defaultWriteAlias: project.default_write_store }
|
|
1769
1824
|
};
|
|
1770
1825
|
}
|
|
1771
1826
|
|
|
1772
1827
|
// src/store/secret-scan.ts
|
|
1773
|
-
var
|
|
1774
|
-
{ rule: "aws-access-key-id", re: /\bAKIA[0-9A-Z]{16}\b
|
|
1775
|
-
{ rule: "private-key-block", re: /-----BEGIN (?:RSA |EC |OPENSSH |DSA |PGP )?PRIVATE KEY
|
|
1776
|
-
{ rule: "openai-api-key", re: /\bsk-[A-Za-z0-9]{20,}\b
|
|
1777
|
-
{ rule: "github-token", re: /\bgh[pousr]_[A-Za-z0-9]{20,}\b
|
|
1778
|
-
{ rule: "slack-token", re: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b
|
|
1828
|
+
var CREDENTIAL_RULES = [
|
|
1829
|
+
{ rule: "aws-access-key-id", re: /\bAKIA[0-9A-Z]{16}\b/, category: "credential" },
|
|
1830
|
+
{ rule: "private-key-block", re: /-----BEGIN (?:RSA |EC |OPENSSH |DSA |PGP )?PRIVATE KEY-----/, category: "credential" },
|
|
1831
|
+
{ rule: "openai-api-key", re: /\bsk-[A-Za-z0-9]{20,}\b/, category: "credential" },
|
|
1832
|
+
{ rule: "github-token", re: /\bgh[pousr]_[A-Za-z0-9]{20,}\b/, category: "credential" },
|
|
1833
|
+
{ rule: "slack-token", re: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/, category: "credential" },
|
|
1779
1834
|
{
|
|
1780
1835
|
rule: "credential-assignment",
|
|
1781
|
-
re: /(?:password|passwd|secret|api[_-]?key|access[_-]?token|token)\s*[:=]\s*['"][^'"\s]{8,}[
|
|
1836
|
+
re: /(?:password|passwd|secret|api[_-]?key|access[_-]?token|token)\s*[:=]\s*(?:"[^'"\s]{8,}"|'[^'"\s]{8,}'|[A-Za-z0-9_./+=:@-]{8,})/i,
|
|
1837
|
+
category: "credential"
|
|
1838
|
+
}
|
|
1839
|
+
];
|
|
1840
|
+
var PII_RULES = [
|
|
1841
|
+
{
|
|
1842
|
+
rule: "email-address",
|
|
1843
|
+
re: /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/i,
|
|
1844
|
+
category: "pii"
|
|
1845
|
+
},
|
|
1846
|
+
{
|
|
1847
|
+
rule: "ipv4-address",
|
|
1848
|
+
re: /\b(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\b/,
|
|
1849
|
+
category: "pii"
|
|
1850
|
+
},
|
|
1851
|
+
{
|
|
1852
|
+
rule: "phone-number",
|
|
1853
|
+
re: /(?<!\d)(?:\+?1[-.\s]?)?(?:\(?\d{3}\)?[-.\s]?)\d{3}[-.\s]?\d{4}(?!\d)/,
|
|
1854
|
+
category: "pii"
|
|
1782
1855
|
}
|
|
1783
1856
|
];
|
|
1857
|
+
var SECRET_RULES = [...CREDENTIAL_RULES, ...PII_RULES];
|
|
1784
1858
|
function scanForSecrets(content) {
|
|
1785
1859
|
const findings = [];
|
|
1786
1860
|
const lines = content.split(/\r?\n/u);
|
|
@@ -1794,12 +1868,26 @@ function scanForSecrets(content) {
|
|
|
1794
1868
|
return findings;
|
|
1795
1869
|
}
|
|
1796
1870
|
function hasSecrets(content) {
|
|
1797
|
-
|
|
1871
|
+
const lines = content.split(/\r?\n/u);
|
|
1872
|
+
for (const line of lines) {
|
|
1873
|
+
for (const { re } of CREDENTIAL_RULES) {
|
|
1874
|
+
if (re.test(line)) {
|
|
1875
|
+
return true;
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
return false;
|
|
1798
1880
|
}
|
|
1799
1881
|
var REDACTION_PLACEHOLDER_PREFIX = "[REDACTED:";
|
|
1800
1882
|
function redactSecrets(content) {
|
|
1883
|
+
return redactByRules(content, SECRET_RULES);
|
|
1884
|
+
}
|
|
1885
|
+
function redactPii(content) {
|
|
1886
|
+
return redactByRules(content, PII_RULES);
|
|
1887
|
+
}
|
|
1888
|
+
function redactByRules(content, rules) {
|
|
1801
1889
|
let out = content;
|
|
1802
|
-
for (const { rule, re } of
|
|
1890
|
+
for (const { rule, re } of rules) {
|
|
1803
1891
|
const flags = re.flags.includes("i") ? "gi" : "g";
|
|
1804
1892
|
out = out.replace(new RegExp(re.source, flags), `${REDACTION_PLACEHOLDER_PREFIX}${rule}]`);
|
|
1805
1893
|
}
|
|
@@ -1922,10 +2010,10 @@ function buildDebugBundle(input) {
|
|
|
1922
2010
|
}
|
|
1923
2011
|
|
|
1924
2012
|
// src/schemas/provenance.ts
|
|
1925
|
-
import { z as
|
|
1926
|
-
var knowledgeProvenanceSchema =
|
|
2013
|
+
import { z as z10 } from "zod";
|
|
2014
|
+
var knowledgeProvenanceSchema = z10.object({
|
|
1927
2015
|
store_uuid: storeUuidSchema,
|
|
1928
|
-
alias:
|
|
2016
|
+
alias: z10.string().min(1),
|
|
1929
2017
|
local_id: localKnowledgeIdSchema,
|
|
1930
2018
|
global_ref: globalRefSchema,
|
|
1931
2019
|
// Optional scope coordinate of the entry (resolution axis); present when the
|
|
@@ -1934,7 +2022,7 @@ var knowledgeProvenanceSchema = z12.object({
|
|
|
1934
2022
|
}).strict();
|
|
1935
2023
|
|
|
1936
2024
|
// src/schemas/mcp-store-contracts.ts
|
|
1937
|
-
import { z as
|
|
2025
|
+
import { z as z11 } from "zod";
|
|
1938
2026
|
var MCP_STORE_AWARE_TOOLS = [
|
|
1939
2027
|
"fab_recall",
|
|
1940
2028
|
"fab_plan_context",
|
|
@@ -1943,14 +2031,14 @@ var MCP_STORE_AWARE_TOOLS = [
|
|
|
1943
2031
|
"fab_extract_knowledge",
|
|
1944
2032
|
"fab_review"
|
|
1945
2033
|
];
|
|
1946
|
-
var storeAwareEntrySchema =
|
|
1947
|
-
stable_id:
|
|
2034
|
+
var storeAwareEntrySchema = z11.object({
|
|
2035
|
+
stable_id: z11.string(),
|
|
1948
2036
|
global_ref: globalRefSchema,
|
|
1949
2037
|
provenance: knowledgeProvenanceSchema
|
|
1950
2038
|
}).strict();
|
|
1951
|
-
var writtenToStoreSchema =
|
|
2039
|
+
var writtenToStoreSchema = z11.object({
|
|
1952
2040
|
store_uuid: storeUuidSchema,
|
|
1953
|
-
alias:
|
|
2041
|
+
alias: z11.string().min(1)
|
|
1954
2042
|
}).strict();
|
|
1955
2043
|
var MCP_STORE_AWARE_CONTRACTS = {
|
|
1956
2044
|
fab_recall: { tool: "fab_recall", surfacesEntries: true, echoesWrittenStore: false },
|
|
@@ -1963,7 +2051,7 @@ var MCP_STORE_AWARE_CONTRACTS = {
|
|
|
1963
2051
|
fab_archive_scan: {
|
|
1964
2052
|
tool: "fab_archive_scan",
|
|
1965
2053
|
surfacesEntries: false,
|
|
1966
|
-
echoesWrittenStore:
|
|
2054
|
+
echoesWrittenStore: false
|
|
1967
2055
|
},
|
|
1968
2056
|
fab_extract_knowledge: {
|
|
1969
2057
|
tool: "fab_extract_knowledge",
|
|
@@ -1974,64 +2062,184 @@ var MCP_STORE_AWARE_CONTRACTS = {
|
|
|
1974
2062
|
};
|
|
1975
2063
|
|
|
1976
2064
|
// src/schemas/bindings-snapshot.ts
|
|
1977
|
-
import { z as
|
|
1978
|
-
var resolvedBindingsSnapshotSchema =
|
|
2065
|
+
import { z as z12 } from "zod";
|
|
2066
|
+
var resolvedBindingsSnapshotSchema = z12.object({
|
|
1979
2067
|
// Schema version of the snapshot document.
|
|
1980
|
-
version:
|
|
2068
|
+
version: z12.literal(1),
|
|
1981
2069
|
// The project this snapshot is bound to (S13).
|
|
1982
|
-
project_id:
|
|
2070
|
+
project_id: z12.string().min(1),
|
|
2071
|
+
// The local runtime binding key. Defaults to project_id for standard repos;
|
|
2072
|
+
// worktrees may isolate state by setting fabric-config.workspace_binding_id.
|
|
2073
|
+
workspace_binding_id: z12.string().min(1),
|
|
1983
2074
|
// ISO-8601 generation timestamp (provenance / staleness signal for doctor).
|
|
1984
|
-
generated_at:
|
|
2075
|
+
generated_at: z12.string().min(1),
|
|
1985
2076
|
// Pre-resolved read-set (required_stores ∪ implicit personal + warnings).
|
|
1986
2077
|
read_set: storeReadSetSchema,
|
|
1987
2078
|
// Pre-resolved active write target for non-personal scopes (null if none).
|
|
1988
|
-
write_target: writeTargetSchema.nullable()
|
|
2079
|
+
write_target: writeTargetSchema.nullable(),
|
|
2080
|
+
// Pre-computed store-backed knowledge counts, snapshotted at write time.
|
|
2081
|
+
// PROVENANCE ONLY: these are store-global counts cached in a per-workspace
|
|
2082
|
+
// file, so they go stale whenever store content changes out-of-band (a `git
|
|
2083
|
+
// pull` in the store repo, a sync run from a *different* bound workspace,
|
|
2084
|
+
// etc.) — the snapshot is only regenerated by install/sync/store-ops in the
|
|
2085
|
+
// workspace that runs them (KT-PIT-0017). Hooks MUST NOT trust these numbers
|
|
2086
|
+
// for nudges; they recount live from `knowledge_store_dirs`. Retained for
|
|
2087
|
+
// doctor provenance + backward-compatible fallback when dirs are absent.
|
|
2088
|
+
knowledge_stats: z12.object({
|
|
2089
|
+
pending_count: z12.number().int().nonnegative(),
|
|
2090
|
+
canonical_count: z12.number().int().nonnegative(),
|
|
2091
|
+
oldest_pending_mtime_ms: z12.number().nonnegative().nullable()
|
|
2092
|
+
}).strict().optional(),
|
|
2093
|
+
// Resolved absolute store ROOT dirs the knowledge_stats were derived from.
|
|
2094
|
+
// STABLE across content sync — they only change when mounts/bindings change,
|
|
2095
|
+
// which DOES regenerate the snapshot. Hooks walk `<dir>/knowledge/<type>` +
|
|
2096
|
+
// `<dir>/knowledge/pending` LIVE off these roots so nudge counts are always
|
|
2097
|
+
// fresh regardless of how store content changed (the underseed / review-
|
|
2098
|
+
// backlog false-positive root cure; pairs with knowledge_stats above).
|
|
2099
|
+
knowledge_store_dirs: z12.array(z12.string().min(1)).optional()
|
|
1989
2100
|
}).strict();
|
|
1990
2101
|
|
|
1991
2102
|
// src/store/bindings.ts
|
|
1992
|
-
import {
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
2103
|
+
import {
|
|
2104
|
+
existsSync as existsSync4,
|
|
2105
|
+
mkdirSync as mkdirSync2,
|
|
2106
|
+
readdirSync as readdirSync3,
|
|
2107
|
+
readFileSync as readFileSync4,
|
|
2108
|
+
renameSync,
|
|
2109
|
+
statSync,
|
|
2110
|
+
unlinkSync,
|
|
2111
|
+
writeFileSync as writeFileSync3
|
|
2112
|
+
} from "fs";
|
|
2113
|
+
import { join as join5, resolve, sep } from "path";
|
|
2114
|
+
var SAFE_BINDING_ID = /^[A-Za-z0-9._-]+$/;
|
|
2115
|
+
function assertSafeBindingId(bindingId) {
|
|
2116
|
+
if (!SAFE_BINDING_ID.test(bindingId) || bindingId.includes("..")) {
|
|
1997
2117
|
throw new Error(
|
|
1998
|
-
`bindingsSnapshotPath: refusing unsafe
|
|
2118
|
+
`bindingsSnapshotPath: refusing unsafe workspace_binding_id ${JSON.stringify(bindingId)} (must match ${SAFE_BINDING_ID} and contain no "..")`
|
|
1999
2119
|
);
|
|
2000
2120
|
}
|
|
2001
2121
|
}
|
|
2002
|
-
function bindingsSnapshotPath(globalRoot,
|
|
2003
|
-
|
|
2004
|
-
const bindingsDir = resolve(
|
|
2005
|
-
const path = resolve(
|
|
2122
|
+
function bindingsSnapshotPath(globalRoot, bindingId) {
|
|
2123
|
+
assertSafeBindingId(bindingId);
|
|
2124
|
+
const bindingsDir = resolve(join5(globalRoot, GLOBAL_STATE_DIR, GLOBAL_BINDINGS_DIR));
|
|
2125
|
+
const path = resolve(join5(bindingsDir, `${bindingId}_resolved.json`));
|
|
2006
2126
|
if (path !== bindingsDir && !path.startsWith(bindingsDir + sep)) {
|
|
2007
|
-
throw new Error(`bindingsSnapshotPath: resolved path escapes bindings dir for ${JSON.stringify(
|
|
2127
|
+
throw new Error(`bindingsSnapshotPath: resolved path escapes bindings dir for ${JSON.stringify(bindingId)}`);
|
|
2008
2128
|
}
|
|
2009
2129
|
return path;
|
|
2010
2130
|
}
|
|
2131
|
+
function resolveWorkspaceBindingId(config) {
|
|
2132
|
+
return config.workspace_binding_id ?? config.project_id;
|
|
2133
|
+
}
|
|
2134
|
+
function countMarkdownFiles(dir) {
|
|
2135
|
+
let count = 0;
|
|
2136
|
+
let oldestMtimeMs = null;
|
|
2137
|
+
if (!existsSync4(dir)) {
|
|
2138
|
+
return { count, oldestMtimeMs };
|
|
2139
|
+
}
|
|
2140
|
+
let entries;
|
|
2141
|
+
try {
|
|
2142
|
+
entries = readdirSync3(dir, { withFileTypes: true });
|
|
2143
|
+
} catch {
|
|
2144
|
+
return { count, oldestMtimeMs };
|
|
2145
|
+
}
|
|
2146
|
+
for (const entry of entries) {
|
|
2147
|
+
const fullPath = join5(dir, entry.name);
|
|
2148
|
+
if (entry.isDirectory()) {
|
|
2149
|
+
const nested = countMarkdownFiles(fullPath);
|
|
2150
|
+
count += nested.count;
|
|
2151
|
+
if (nested.oldestMtimeMs !== null && (oldestMtimeMs === null || nested.oldestMtimeMs < oldestMtimeMs)) {
|
|
2152
|
+
oldestMtimeMs = nested.oldestMtimeMs;
|
|
2153
|
+
}
|
|
2154
|
+
continue;
|
|
2155
|
+
}
|
|
2156
|
+
if (!entry.isFile() || !entry.name.endsWith(".md")) {
|
|
2157
|
+
continue;
|
|
2158
|
+
}
|
|
2159
|
+
let mtimeMs;
|
|
2160
|
+
try {
|
|
2161
|
+
mtimeMs = statSync(fullPath).mtimeMs;
|
|
2162
|
+
} catch {
|
|
2163
|
+
continue;
|
|
2164
|
+
}
|
|
2165
|
+
count += 1;
|
|
2166
|
+
if (oldestMtimeMs === null || mtimeMs < oldestMtimeMs) {
|
|
2167
|
+
oldestMtimeMs = mtimeMs;
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
return { count, oldestMtimeMs };
|
|
2171
|
+
}
|
|
2172
|
+
function collectKnowledgeStats(globalRoot, resolveInput, readSet) {
|
|
2173
|
+
let pendingCount = 0;
|
|
2174
|
+
let oldestPendingMtimeMs = null;
|
|
2175
|
+
let canonicalCount = 0;
|
|
2176
|
+
const storeDirs = [];
|
|
2177
|
+
for (const store of readSet.stores) {
|
|
2178
|
+
const mounted = resolveInput.mountedStores.find((entry) => entry.store_uuid === store.store_uuid) ?? {
|
|
2179
|
+
store_uuid: store.store_uuid
|
|
2180
|
+
};
|
|
2181
|
+
const storeDir = join5(globalRoot, storeRelativePathForMount(mounted));
|
|
2182
|
+
storeDirs.push(storeDir);
|
|
2183
|
+
for (const type of STORE_KNOWLEDGE_TYPE_DIRS) {
|
|
2184
|
+
const canonical = countMarkdownFiles(join5(storeDir, STORE_LAYOUT.knowledgeDir, type));
|
|
2185
|
+
canonicalCount += canonical.count;
|
|
2186
|
+
}
|
|
2187
|
+
const pending = countMarkdownFiles(join5(storeDir, STORE_LAYOUT.knowledgeDir, "pending"));
|
|
2188
|
+
pendingCount += pending.count;
|
|
2189
|
+
if (pending.oldestMtimeMs !== null && (oldestPendingMtimeMs === null || pending.oldestMtimeMs < oldestPendingMtimeMs)) {
|
|
2190
|
+
oldestPendingMtimeMs = pending.oldestMtimeMs;
|
|
2191
|
+
}
|
|
2192
|
+
}
|
|
2193
|
+
return {
|
|
2194
|
+
stats: {
|
|
2195
|
+
pending_count: pendingCount,
|
|
2196
|
+
canonical_count: canonicalCount,
|
|
2197
|
+
oldest_pending_mtime_ms: oldestPendingMtimeMs
|
|
2198
|
+
},
|
|
2199
|
+
storeDirs
|
|
2200
|
+
};
|
|
2201
|
+
}
|
|
2202
|
+
function atomicWriteJsonSync(path, value) {
|
|
2203
|
+
const tmpPath = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
2204
|
+
try {
|
|
2205
|
+
writeFileSync3(tmpPath, `${JSON.stringify(value, null, 2)}
|
|
2206
|
+
`, "utf8");
|
|
2207
|
+
renameSync(tmpPath, path);
|
|
2208
|
+
} catch (error) {
|
|
2209
|
+
try {
|
|
2210
|
+
unlinkSync(tmpPath);
|
|
2211
|
+
} catch {
|
|
2212
|
+
}
|
|
2213
|
+
throw error;
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2011
2216
|
function writeBindingsSnapshot(options) {
|
|
2012
2217
|
const resolver = createStoreResolver();
|
|
2013
2218
|
const read_set = resolver.resolveReadSet(options.resolveInput);
|
|
2014
2219
|
const { target } = resolver.resolveWriteTarget(options.resolveInput, options.writeScope);
|
|
2220
|
+
const { stats, storeDirs } = collectKnowledgeStats(options.globalRoot, options.resolveInput, read_set);
|
|
2015
2221
|
const snapshot = resolvedBindingsSnapshotSchema.parse({
|
|
2016
2222
|
version: 1,
|
|
2017
2223
|
project_id: options.projectId,
|
|
2224
|
+
workspace_binding_id: options.workspaceBindingId ?? options.projectId,
|
|
2018
2225
|
generated_at: options.now,
|
|
2019
2226
|
read_set,
|
|
2020
|
-
write_target: target
|
|
2227
|
+
write_target: target,
|
|
2228
|
+
knowledge_stats: stats,
|
|
2229
|
+
knowledge_store_dirs: storeDirs
|
|
2021
2230
|
});
|
|
2022
|
-
const path = bindingsSnapshotPath(options.globalRoot,
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
`, "utf8");
|
|
2231
|
+
const path = bindingsSnapshotPath(options.globalRoot, snapshot.workspace_binding_id);
|
|
2232
|
+
mkdirSync2(join5(path, ".."), { recursive: true });
|
|
2233
|
+
atomicWriteJsonSync(path, snapshot);
|
|
2026
2234
|
return snapshot;
|
|
2027
2235
|
}
|
|
2028
2236
|
function readBindingsSnapshot(globalRoot, projectId) {
|
|
2029
2237
|
const path = bindingsSnapshotPath(globalRoot, projectId);
|
|
2030
|
-
if (!
|
|
2238
|
+
if (!existsSync4(path)) {
|
|
2031
2239
|
return null;
|
|
2032
2240
|
}
|
|
2033
2241
|
try {
|
|
2034
|
-
const parsed = resolvedBindingsSnapshotSchema.safeParse(JSON.parse(
|
|
2242
|
+
const parsed = resolvedBindingsSnapshotSchema.safeParse(JSON.parse(readFileSync4(path, "utf8")));
|
|
2035
2243
|
return parsed.success ? parsed.data : null;
|
|
2036
2244
|
} catch {
|
|
2037
2245
|
return null;
|
|
@@ -2040,7 +2248,9 @@ function readBindingsSnapshot(globalRoot, projectId) {
|
|
|
2040
2248
|
|
|
2041
2249
|
// src/store/store-lifecycle.ts
|
|
2042
2250
|
function findMountedStore(config, aliasOrUuid) {
|
|
2043
|
-
return config.stores.find(
|
|
2251
|
+
return config.stores.find(
|
|
2252
|
+
(s) => s.alias === aliasOrUuid || s.store_uuid === aliasOrUuid || s.mount_name === aliasOrUuid
|
|
2253
|
+
);
|
|
2044
2254
|
}
|
|
2045
2255
|
function addMountedStore(config, store) {
|
|
2046
2256
|
const aliasClash = config.stores.find(
|
|
@@ -2051,12 +2261,32 @@ function addMountedStore(config, store) {
|
|
|
2051
2261
|
`alias '${store.alias}' already mounts store ${aliasClash.store_uuid}; choose another alias`
|
|
2052
2262
|
);
|
|
2053
2263
|
}
|
|
2264
|
+
const mountNameClash = store.mount_name === void 0 ? void 0 : config.stores.find(
|
|
2265
|
+
(s) => s.mount_name === store.mount_name && s.store_uuid !== store.store_uuid
|
|
2266
|
+
);
|
|
2267
|
+
if (mountNameClash !== void 0) {
|
|
2268
|
+
throw new Error(
|
|
2269
|
+
`mount_name '${store.mount_name}' already maps to store ${mountNameClash.store_uuid}; choose another mount_name`
|
|
2270
|
+
);
|
|
2271
|
+
}
|
|
2054
2272
|
const sanitized = store.remote === void 0 ? store : { ...store, remote: scrubRemoteUrl(store.remote) };
|
|
2055
2273
|
store = sanitized;
|
|
2056
2274
|
const existing = config.stores.find((s) => s.store_uuid === store.store_uuid);
|
|
2057
2275
|
const stores = existing === void 0 ? [...config.stores, store] : config.stores.map((s) => s.store_uuid === store.store_uuid ? store : s);
|
|
2058
2276
|
return { ...config, stores };
|
|
2059
2277
|
}
|
|
2278
|
+
function disambiguateAlias(existingAliases, desired) {
|
|
2279
|
+
const taken = new Set(existingAliases);
|
|
2280
|
+
if (!taken.has(desired)) {
|
|
2281
|
+
return desired;
|
|
2282
|
+
}
|
|
2283
|
+
for (let n = 2; ; n += 1) {
|
|
2284
|
+
const candidate = `${desired}-${n}`;
|
|
2285
|
+
if (!taken.has(candidate)) {
|
|
2286
|
+
return candidate;
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2060
2290
|
function detachMountedStore(config, alias) {
|
|
2061
2291
|
const detached = config.stores.find((s) => s.alias === alias) ?? null;
|
|
2062
2292
|
if (detached === null) {
|
|
@@ -2085,155 +2315,155 @@ function explainStore(config, alias) {
|
|
|
2085
2315
|
}
|
|
2086
2316
|
|
|
2087
2317
|
// src/schemas/forensic-report.ts
|
|
2088
|
-
import { z as
|
|
2089
|
-
var forensicCodeSampleSchema =
|
|
2090
|
-
path:
|
|
2091
|
-
lines:
|
|
2092
|
-
snippet:
|
|
2093
|
-
pattern_hint:
|
|
2094
|
-
});
|
|
2095
|
-
var forensicEvidenceAnchorSchema =
|
|
2096
|
-
file:
|
|
2097
|
-
line:
|
|
2098
|
-
snippet:
|
|
2099
|
-
});
|
|
2100
|
-
var forensicAssertionCoverageSchema =
|
|
2101
|
-
ratio:
|
|
2102
|
-
total:
|
|
2103
|
-
matched:
|
|
2104
|
-
co_occurring_patterns:
|
|
2105
|
-
});
|
|
2106
|
-
var forensicAssertionSchema =
|
|
2107
|
-
type:
|
|
2108
|
-
statement:
|
|
2109
|
-
confidence:
|
|
2110
|
-
evidence:
|
|
2318
|
+
import { z as z13 } from "zod";
|
|
2319
|
+
var forensicCodeSampleSchema = z13.object({
|
|
2320
|
+
path: z13.string(),
|
|
2321
|
+
lines: z13.string(),
|
|
2322
|
+
snippet: z13.string(),
|
|
2323
|
+
pattern_hint: z13.string()
|
|
2324
|
+
});
|
|
2325
|
+
var forensicEvidenceAnchorSchema = z13.object({
|
|
2326
|
+
file: z13.string(),
|
|
2327
|
+
line: z13.string(),
|
|
2328
|
+
snippet: z13.string()
|
|
2329
|
+
});
|
|
2330
|
+
var forensicAssertionCoverageSchema = z13.object({
|
|
2331
|
+
ratio: z13.number().min(0).max(1),
|
|
2332
|
+
total: z13.number().int().nonnegative(),
|
|
2333
|
+
matched: z13.number().int().nonnegative(),
|
|
2334
|
+
co_occurring_patterns: z13.array(z13.string())
|
|
2335
|
+
});
|
|
2336
|
+
var forensicAssertionSchema = z13.object({
|
|
2337
|
+
type: z13.enum(["framework", "pattern", "invariant", "domain"]),
|
|
2338
|
+
statement: z13.string(),
|
|
2339
|
+
confidence: z13.enum(["HIGH", "MEDIUM", "LOW"]),
|
|
2340
|
+
evidence: z13.array(forensicEvidenceAnchorSchema),
|
|
2111
2341
|
coverage: forensicAssertionCoverageSchema,
|
|
2112
|
-
proposed_rule:
|
|
2113
|
-
alternatives:
|
|
2114
|
-
});
|
|
2115
|
-
var forensicTopologySchema =
|
|
2116
|
-
total_files:
|
|
2117
|
-
by_ext:
|
|
2118
|
-
key_dirs:
|
|
2119
|
-
max_depth:
|
|
2120
|
-
});
|
|
2121
|
-
var forensicEntryPointSchema =
|
|
2122
|
-
path:
|
|
2123
|
-
reason:
|
|
2124
|
-
size_bytes:
|
|
2125
|
-
});
|
|
2126
|
-
var forensicFrameworkSchema =
|
|
2127
|
-
kind:
|
|
2128
|
-
version:
|
|
2129
|
-
subkind:
|
|
2130
|
-
evidence:
|
|
2131
|
-
});
|
|
2132
|
-
var forensicReadmeSchema =
|
|
2133
|
-
quality:
|
|
2134
|
-
line_count:
|
|
2135
|
-
has_contributing:
|
|
2136
|
-
});
|
|
2137
|
-
var candidateFileEntrySchema =
|
|
2138
|
-
path:
|
|
2139
|
-
family:
|
|
2140
|
-
rationale:
|
|
2141
|
-
});
|
|
2142
|
-
var forensicSamplingBudgetSchema =
|
|
2143
|
-
max_files:
|
|
2144
|
-
max_lines_per_file:
|
|
2145
|
-
});
|
|
2146
|
-
var forensicReportSchema =
|
|
2147
|
-
version:
|
|
2148
|
-
generated_at:
|
|
2149
|
-
generated_by:
|
|
2150
|
-
target:
|
|
2151
|
-
project_name:
|
|
2342
|
+
proposed_rule: z13.string().optional(),
|
|
2343
|
+
alternatives: z13.array(z13.string()).optional()
|
|
2344
|
+
});
|
|
2345
|
+
var forensicTopologySchema = z13.object({
|
|
2346
|
+
total_files: z13.number().int().nonnegative(),
|
|
2347
|
+
by_ext: z13.record(z13.number().int().nonnegative()),
|
|
2348
|
+
key_dirs: z13.array(z13.string()),
|
|
2349
|
+
max_depth: z13.number().int().nonnegative()
|
|
2350
|
+
});
|
|
2351
|
+
var forensicEntryPointSchema = z13.object({
|
|
2352
|
+
path: z13.string(),
|
|
2353
|
+
reason: z13.string(),
|
|
2354
|
+
size_bytes: z13.number().int().nonnegative().optional()
|
|
2355
|
+
});
|
|
2356
|
+
var forensicFrameworkSchema = z13.object({
|
|
2357
|
+
kind: z13.string(),
|
|
2358
|
+
version: z13.string(),
|
|
2359
|
+
subkind: z13.string(),
|
|
2360
|
+
evidence: z13.array(z13.string())
|
|
2361
|
+
});
|
|
2362
|
+
var forensicReadmeSchema = z13.object({
|
|
2363
|
+
quality: z13.enum(["missing", "stub", "ok"]),
|
|
2364
|
+
line_count: z13.number().int().nonnegative(),
|
|
2365
|
+
has_contributing: z13.boolean()
|
|
2366
|
+
});
|
|
2367
|
+
var candidateFileEntrySchema = z13.object({
|
|
2368
|
+
path: z13.string(),
|
|
2369
|
+
family: z13.enum(["entry", "component", "config", "test", "domain"]),
|
|
2370
|
+
rationale: z13.string()
|
|
2371
|
+
});
|
|
2372
|
+
var forensicSamplingBudgetSchema = z13.object({
|
|
2373
|
+
max_files: z13.literal(15),
|
|
2374
|
+
max_lines_per_file: z13.literal(100)
|
|
2375
|
+
});
|
|
2376
|
+
var forensicReportSchema = z13.object({
|
|
2377
|
+
version: z13.string(),
|
|
2378
|
+
generated_at: z13.string(),
|
|
2379
|
+
generated_by: z13.string(),
|
|
2380
|
+
target: z13.string(),
|
|
2381
|
+
project_name: z13.string(),
|
|
2152
2382
|
framework: forensicFrameworkSchema,
|
|
2153
2383
|
topology: forensicTopologySchema,
|
|
2154
|
-
entry_points:
|
|
2155
|
-
code_samples:
|
|
2156
|
-
assertions:
|
|
2157
|
-
candidate_files:
|
|
2384
|
+
entry_points: z13.array(forensicEntryPointSchema),
|
|
2385
|
+
code_samples: z13.array(forensicCodeSampleSchema),
|
|
2386
|
+
assertions: z13.array(forensicAssertionSchema),
|
|
2387
|
+
candidate_files: z13.array(candidateFileEntrySchema),
|
|
2158
2388
|
sampling_budget: forensicSamplingBudgetSchema,
|
|
2159
2389
|
readme: forensicReadmeSchema,
|
|
2160
|
-
recommendations_for_skill:
|
|
2390
|
+
recommendations_for_skill: z13.array(z13.string()).optional()
|
|
2161
2391
|
});
|
|
2162
2392
|
|
|
2163
2393
|
// src/schemas/init-context.ts
|
|
2164
|
-
import { z as
|
|
2165
|
-
var initContextFrameworkSchema =
|
|
2166
|
-
kind:
|
|
2167
|
-
version:
|
|
2168
|
-
subkind:
|
|
2169
|
-
});
|
|
2170
|
-
var initContextInvariantConfidenceSnapshotSchema =
|
|
2171
|
-
confidence:
|
|
2172
|
-
evidence_refs:
|
|
2173
|
-
});
|
|
2174
|
-
var initContextSourceEvidenceSchema =
|
|
2175
|
-
file:
|
|
2176
|
-
lines:
|
|
2177
|
-
});
|
|
2178
|
-
var initContextInvariantSchema =
|
|
2179
|
-
type:
|
|
2180
|
-
rule:
|
|
2181
|
-
rationale:
|
|
2394
|
+
import { z as z14 } from "zod";
|
|
2395
|
+
var initContextFrameworkSchema = z14.object({
|
|
2396
|
+
kind: z14.string(),
|
|
2397
|
+
version: z14.string(),
|
|
2398
|
+
subkind: z14.string()
|
|
2399
|
+
});
|
|
2400
|
+
var initContextInvariantConfidenceSnapshotSchema = z14.object({
|
|
2401
|
+
confidence: z14.enum(["HIGH", "MEDIUM", "LOW"]),
|
|
2402
|
+
evidence_refs: z14.array(z14.string())
|
|
2403
|
+
});
|
|
2404
|
+
var initContextSourceEvidenceSchema = z14.object({
|
|
2405
|
+
file: z14.string(),
|
|
2406
|
+
lines: z14.string()
|
|
2407
|
+
});
|
|
2408
|
+
var initContextInvariantSchema = z14.object({
|
|
2409
|
+
type: z14.enum(["ban", "require", "protect"]),
|
|
2410
|
+
rule: z14.string(),
|
|
2411
|
+
rationale: z14.string().optional(),
|
|
2182
2412
|
confidence_snapshot: initContextInvariantConfidenceSnapshotSchema.optional(),
|
|
2183
|
-
source_evidence:
|
|
2184
|
-
});
|
|
2185
|
-
var initContextDomainGroupSchema =
|
|
2186
|
-
name:
|
|
2187
|
-
paths:
|
|
2188
|
-
summary:
|
|
2189
|
-
topology_type:
|
|
2190
|
-
target_path:
|
|
2191
|
-
});
|
|
2192
|
-
var initContextInterviewTrailEntrySchema =
|
|
2193
|
-
phase:
|
|
2194
|
-
question:
|
|
2195
|
-
answer:
|
|
2196
|
-
presentation:
|
|
2197
|
-
user_corrections:
|
|
2198
|
-
});
|
|
2199
|
-
var initContextSchema =
|
|
2413
|
+
source_evidence: z14.array(initContextSourceEvidenceSchema).optional()
|
|
2414
|
+
});
|
|
2415
|
+
var initContextDomainGroupSchema = z14.object({
|
|
2416
|
+
name: z14.string(),
|
|
2417
|
+
paths: z14.array(z14.string()),
|
|
2418
|
+
summary: z14.string().optional(),
|
|
2419
|
+
topology_type: z14.enum(["mirror", "cross-cutting"]).optional(),
|
|
2420
|
+
target_path: z14.string().optional()
|
|
2421
|
+
});
|
|
2422
|
+
var initContextInterviewTrailEntrySchema = z14.object({
|
|
2423
|
+
phase: z14.string(),
|
|
2424
|
+
question: z14.string(),
|
|
2425
|
+
answer: z14.string(),
|
|
2426
|
+
presentation: z14.string().optional(),
|
|
2427
|
+
user_corrections: z14.array(z14.string()).optional()
|
|
2428
|
+
});
|
|
2429
|
+
var initContextSchema = z14.object({
|
|
2200
2430
|
framework: initContextFrameworkSchema,
|
|
2201
|
-
architecture_patterns:
|
|
2202
|
-
invariants:
|
|
2203
|
-
domain_groups:
|
|
2204
|
-
interview_trail:
|
|
2205
|
-
forensic_ref:
|
|
2431
|
+
architecture_patterns: z14.array(z14.string()),
|
|
2432
|
+
invariants: z14.array(initContextInvariantSchema),
|
|
2433
|
+
domain_groups: z14.array(initContextDomainGroupSchema),
|
|
2434
|
+
interview_trail: z14.array(initContextInterviewTrailEntrySchema),
|
|
2435
|
+
forensic_ref: z14.string()
|
|
2206
2436
|
});
|
|
2207
2437
|
|
|
2208
2438
|
// src/schemas/events.ts
|
|
2209
|
-
import { z as
|
|
2210
|
-
var metaUpdatedEventSchema =
|
|
2211
|
-
type:
|
|
2439
|
+
import { z as z15 } from "zod";
|
|
2440
|
+
var metaUpdatedEventSchema = z15.object({
|
|
2441
|
+
type: z15.literal("meta:updated"),
|
|
2212
2442
|
payload: agentsMetaSchema
|
|
2213
2443
|
});
|
|
2214
|
-
var lockDriftEventSchema =
|
|
2215
|
-
type:
|
|
2216
|
-
payload:
|
|
2217
|
-
locked:
|
|
2218
|
-
drifted:
|
|
2444
|
+
var lockDriftEventSchema = z15.object({
|
|
2445
|
+
type: z15.literal("lock:drift"),
|
|
2446
|
+
payload: z15.object({
|
|
2447
|
+
locked: z15.array(humanLockEntrySchema),
|
|
2448
|
+
drifted: z15.array(humanLockEntrySchema)
|
|
2219
2449
|
})
|
|
2220
2450
|
});
|
|
2221
|
-
var lockApprovedEventSchema =
|
|
2222
|
-
type:
|
|
2223
|
-
payload:
|
|
2224
|
-
locked:
|
|
2225
|
-
approved:
|
|
2451
|
+
var lockApprovedEventSchema = z15.object({
|
|
2452
|
+
type: z15.literal("lock:approved"),
|
|
2453
|
+
payload: z15.object({
|
|
2454
|
+
locked: z15.array(humanLockEntrySchema),
|
|
2455
|
+
approved: z15.array(humanLockEntrySchema)
|
|
2226
2456
|
})
|
|
2227
2457
|
});
|
|
2228
|
-
var ledgerAppendedEventSchema =
|
|
2229
|
-
type:
|
|
2458
|
+
var ledgerAppendedEventSchema = z15.object({
|
|
2459
|
+
type: z15.literal("ledger:appended"),
|
|
2230
2460
|
payload: ledgerEntrySchema
|
|
2231
2461
|
});
|
|
2232
|
-
var driftDetectedEventSchema =
|
|
2233
|
-
type:
|
|
2462
|
+
var driftDetectedEventSchema = z15.object({
|
|
2463
|
+
type: z15.literal("drift:detected"),
|
|
2234
2464
|
payload: forensicReportSchema
|
|
2235
2465
|
});
|
|
2236
|
-
var fabricEventSchema =
|
|
2466
|
+
var fabricEventSchema = z15.discriminatedUnion("type", [
|
|
2237
2467
|
metaUpdatedEventSchema,
|
|
2238
2468
|
lockDriftEventSchema,
|
|
2239
2469
|
lockApprovedEventSchema,
|
|
@@ -2242,7 +2472,7 @@ var fabricEventSchema = z17.discriminatedUnion("type", [
|
|
|
2242
2472
|
]);
|
|
2243
2473
|
|
|
2244
2474
|
// src/schemas/event-ledger.ts
|
|
2245
|
-
import { z as
|
|
2475
|
+
import { z as z16 } from "zod";
|
|
2246
2476
|
|
|
2247
2477
|
// src/cite-line-parser.ts
|
|
2248
2478
|
var ID_RE = /^K[TP]-[A-Z]+-\d+$/;
|
|
@@ -2256,17 +2486,12 @@ function splitStorePrefix(token) {
|
|
|
2256
2486
|
return colon === -1 ? { store: null, id: token } : { store: token.slice(0, colon), id: token.slice(colon + 1) };
|
|
2257
2487
|
}
|
|
2258
2488
|
var CHAINED_FROM_ID_RE = /chained-from\s+(K[TP]-[A-Z]+-\d+)/i;
|
|
2259
|
-
var LEGACY_CITE_TAG_REMAP = {
|
|
2260
|
-
planned: "applied",
|
|
2261
|
-
recalled: "applied",
|
|
2262
|
-
"chained-from": "applied"
|
|
2263
|
-
};
|
|
2264
2489
|
function normalizeCiteTag(rawTag) {
|
|
2265
2490
|
const head = rawTag.trim().split(/[\s:]+/)[0].toLowerCase();
|
|
2266
2491
|
if (head === "applied" || head === "dismissed" || head === "none") {
|
|
2267
2492
|
return head;
|
|
2268
2493
|
}
|
|
2269
|
-
return
|
|
2494
|
+
return "none";
|
|
2270
2495
|
}
|
|
2271
2496
|
function parseTag(rawTag) {
|
|
2272
2497
|
if (!rawTag) return "none";
|
|
@@ -2354,146 +2579,131 @@ function parseCiteLine(raw) {
|
|
|
2354
2579
|
}
|
|
2355
2580
|
|
|
2356
2581
|
// src/schemas/event-ledger.ts
|
|
2357
|
-
var citeTagSchema =
|
|
2582
|
+
var citeTagSchema = z16.preprocess(
|
|
2358
2583
|
(value) => typeof value === "string" ? normalizeCiteTag(value) : value,
|
|
2359
|
-
|
|
2584
|
+
z16.enum(["applied", "dismissed", "none"])
|
|
2360
2585
|
);
|
|
2361
2586
|
var eventLedgerEnvelopeSchema = {
|
|
2362
|
-
kind:
|
|
2363
|
-
id:
|
|
2364
|
-
ts:
|
|
2365
|
-
schema_version:
|
|
2366
|
-
correlation_id:
|
|
2367
|
-
session_id:
|
|
2587
|
+
kind: z16.literal("fabric-event"),
|
|
2588
|
+
id: z16.string(),
|
|
2589
|
+
ts: z16.number().int().nonnegative(),
|
|
2590
|
+
schema_version: z16.literal(1),
|
|
2591
|
+
correlation_id: z16.string().optional(),
|
|
2592
|
+
session_id: z16.string().optional()
|
|
2368
2593
|
};
|
|
2369
|
-
var stringRecordSchema =
|
|
2370
|
-
var knowledgeContextPlannedEventSchema =
|
|
2594
|
+
var stringRecordSchema = z16.record(z16.string());
|
|
2595
|
+
var knowledgeContextPlannedEventSchema = z16.object({
|
|
2371
2596
|
...eventLedgerEnvelopeSchema,
|
|
2372
|
-
event_type:
|
|
2373
|
-
target_paths:
|
|
2374
|
-
required_stable_ids:
|
|
2375
|
-
ai_selectable_stable_ids:
|
|
2376
|
-
final_stable_ids:
|
|
2377
|
-
selection_token:
|
|
2378
|
-
client_hash:
|
|
2379
|
-
intent:
|
|
2380
|
-
known_tech:
|
|
2381
|
-
diagnostics:
|
|
2382
|
-
});
|
|
2383
|
-
var knowledgeSelectionEventSchema =
|
|
2597
|
+
event_type: z16.literal("knowledge_context_planned"),
|
|
2598
|
+
target_paths: z16.array(z16.string()),
|
|
2599
|
+
required_stable_ids: z16.array(z16.string()),
|
|
2600
|
+
ai_selectable_stable_ids: z16.array(z16.string()),
|
|
2601
|
+
final_stable_ids: z16.array(z16.string()),
|
|
2602
|
+
selection_token: z16.string().optional(),
|
|
2603
|
+
client_hash: z16.string().optional(),
|
|
2604
|
+
intent: z16.string().optional(),
|
|
2605
|
+
known_tech: z16.array(z16.string()).optional(),
|
|
2606
|
+
diagnostics: z16.array(z16.unknown()).optional()
|
|
2607
|
+
});
|
|
2608
|
+
var knowledgeSelectionEventSchema = z16.object({
|
|
2384
2609
|
...eventLedgerEnvelopeSchema,
|
|
2385
|
-
event_type:
|
|
2386
|
-
selection_token:
|
|
2387
|
-
target_paths:
|
|
2388
|
-
required_stable_ids:
|
|
2389
|
-
ai_selectable_stable_ids:
|
|
2390
|
-
ai_selected_stable_ids:
|
|
2391
|
-
final_stable_ids:
|
|
2610
|
+
event_type: z16.literal("knowledge_selection"),
|
|
2611
|
+
selection_token: z16.string(),
|
|
2612
|
+
target_paths: z16.array(z16.string()),
|
|
2613
|
+
required_stable_ids: z16.array(z16.string()),
|
|
2614
|
+
ai_selectable_stable_ids: z16.array(z16.string()),
|
|
2615
|
+
ai_selected_stable_ids: z16.array(z16.string()),
|
|
2616
|
+
final_stable_ids: z16.array(z16.string()),
|
|
2392
2617
|
ai_selection_reasons: stringRecordSchema,
|
|
2393
|
-
rejected_stable_ids:
|
|
2394
|
-
ignored_stable_ids:
|
|
2618
|
+
rejected_stable_ids: z16.array(z16.string()),
|
|
2619
|
+
ignored_stable_ids: z16.array(z16.string())
|
|
2395
2620
|
});
|
|
2396
|
-
var knowledgeSectionsFetchedEventSchema =
|
|
2621
|
+
var knowledgeSectionsFetchedEventSchema = z16.object({
|
|
2397
2622
|
...eventLedgerEnvelopeSchema,
|
|
2398
|
-
event_type:
|
|
2399
|
-
selection_token:
|
|
2400
|
-
target_paths:
|
|
2401
|
-
requested_sections:
|
|
2402
|
-
final_stable_ids:
|
|
2403
|
-
ai_selected_stable_ids:
|
|
2404
|
-
diagnostics:
|
|
2405
|
-
});
|
|
2406
|
-
var editIntentCheckedEventSchema =
|
|
2623
|
+
event_type: z16.literal("knowledge_sections_fetched"),
|
|
2624
|
+
selection_token: z16.string(),
|
|
2625
|
+
target_paths: z16.array(z16.string()).optional(),
|
|
2626
|
+
requested_sections: z16.array(z16.string()),
|
|
2627
|
+
final_stable_ids: z16.array(z16.string()),
|
|
2628
|
+
ai_selected_stable_ids: z16.array(z16.string()),
|
|
2629
|
+
diagnostics: z16.array(z16.unknown()).optional()
|
|
2630
|
+
});
|
|
2631
|
+
var editIntentCheckedEventSchema = z16.object({
|
|
2407
2632
|
...eventLedgerEnvelopeSchema,
|
|
2408
|
-
event_type:
|
|
2409
|
-
path:
|
|
2410
|
-
compliant:
|
|
2411
|
-
intent:
|
|
2412
|
-
ledger_entry_id:
|
|
2633
|
+
event_type: z16.literal("edit_intent_checked"),
|
|
2634
|
+
path: z16.string(),
|
|
2635
|
+
compliant: z16.boolean(),
|
|
2636
|
+
intent: z16.string(),
|
|
2637
|
+
ledger_entry_id: z16.string(),
|
|
2413
2638
|
// rc.35 TASK-07 (P0-2): add "hook" — emitted by the PreToolUse narrow hook
|
|
2414
2639
|
// for every Edit/Write/MultiEdit fire so cite-coverage doctor metrics see
|
|
2415
2640
|
// actual edit signals (previously editsTouched was permanently 0 because
|
|
2416
2641
|
// no production caller of appendLedgerEntry existed).
|
|
2417
|
-
ledger_source:
|
|
2418
|
-
commit_sha:
|
|
2419
|
-
parent_sha:
|
|
2420
|
-
parent_ledger_entry_id:
|
|
2421
|
-
diff_stat:
|
|
2422
|
-
annotation:
|
|
2423
|
-
matched_rule_context_ts:
|
|
2424
|
-
window_ms:
|
|
2425
|
-
});
|
|
2426
|
-
var knowledgeDriftDetectedEventSchema =
|
|
2642
|
+
ledger_source: z16.enum(["ai", "human", "hook"]).optional(),
|
|
2643
|
+
commit_sha: z16.string().optional(),
|
|
2644
|
+
parent_sha: z16.string().optional(),
|
|
2645
|
+
parent_ledger_entry_id: z16.string().optional(),
|
|
2646
|
+
diff_stat: z16.string().optional(),
|
|
2647
|
+
annotation: z16.string().optional(),
|
|
2648
|
+
matched_rule_context_ts: z16.number().int().nonnegative().nullable(),
|
|
2649
|
+
window_ms: z16.number().int().nonnegative()
|
|
2650
|
+
});
|
|
2651
|
+
var knowledgeDriftDetectedEventSchema = z16.object({
|
|
2427
2652
|
...eventLedgerEnvelopeSchema,
|
|
2428
|
-
event_type:
|
|
2429
|
-
revision:
|
|
2430
|
-
drifted_stable_ids:
|
|
2431
|
-
missing_files:
|
|
2432
|
-
stale_files:
|
|
2433
|
-
details:
|
|
2434
|
-
|
|
2435
|
-
file:
|
|
2436
|
-
stable_id:
|
|
2437
|
-
expected_hash:
|
|
2438
|
-
actual_hash:
|
|
2653
|
+
event_type: z16.literal("knowledge_drift_detected"),
|
|
2654
|
+
revision: z16.string().optional(),
|
|
2655
|
+
drifted_stable_ids: z16.array(z16.string()),
|
|
2656
|
+
missing_files: z16.array(z16.string()),
|
|
2657
|
+
stale_files: z16.array(z16.string()),
|
|
2658
|
+
details: z16.array(
|
|
2659
|
+
z16.object({
|
|
2660
|
+
file: z16.string(),
|
|
2661
|
+
stable_id: z16.string(),
|
|
2662
|
+
expected_hash: z16.string(),
|
|
2663
|
+
actual_hash: z16.string().nullable()
|
|
2439
2664
|
})
|
|
2440
2665
|
).optional()
|
|
2441
2666
|
});
|
|
2442
|
-
var mcpEventLedgerEventSchema =
|
|
2443
|
-
...eventLedgerEnvelopeSchema,
|
|
2444
|
-
event_type: z18.literal("mcp_event"),
|
|
2445
|
-
mcp_event_id: z18.string(),
|
|
2446
|
-
stream_id: z18.string(),
|
|
2447
|
-
message: z18.unknown()
|
|
2448
|
-
});
|
|
2449
|
-
var reapplyCompletedEventSchema = z18.object({
|
|
2667
|
+
var mcpEventLedgerEventSchema = z16.object({
|
|
2450
2668
|
...eventLedgerEnvelopeSchema,
|
|
2451
|
-
event_type:
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2669
|
+
event_type: z16.literal("mcp_event"),
|
|
2670
|
+
mcp_event_id: z16.string(),
|
|
2671
|
+
stream_id: z16.string(),
|
|
2672
|
+
message: z16.unknown()
|
|
2455
2673
|
});
|
|
2456
|
-
var
|
|
2674
|
+
var reapplyCompletedEventSchema = z16.object({
|
|
2457
2675
|
...eventLedgerEnvelopeSchema,
|
|
2458
|
-
event_type:
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2676
|
+
event_type: z16.literal("reapply_completed"),
|
|
2677
|
+
preserved_ledger: z16.boolean(),
|
|
2678
|
+
preserved_meta: z16.boolean(),
|
|
2679
|
+
rules_count: z16.number().int().nonnegative()
|
|
2462
2680
|
});
|
|
2463
|
-
var
|
|
2681
|
+
var installDiffAppliedEventSchema = z16.object({
|
|
2464
2682
|
...eventLedgerEnvelopeSchema,
|
|
2465
|
-
event_type:
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2683
|
+
event_type: z16.literal("install_diff_applied"),
|
|
2684
|
+
applied: z16.array(z16.string()),
|
|
2685
|
+
canonical: z16.array(z16.string()),
|
|
2686
|
+
drifted: z16.array(z16.string())
|
|
2469
2687
|
});
|
|
2470
|
-
var
|
|
2688
|
+
var eventLedgerTruncatedEventSchema = z16.object({
|
|
2471
2689
|
...eventLedgerEnvelopeSchema,
|
|
2472
|
-
event_type:
|
|
2473
|
-
|
|
2474
|
-
|
|
2690
|
+
event_type: z16.literal("event_ledger_truncated"),
|
|
2691
|
+
byte_offset: z16.number().int().nonnegative(),
|
|
2692
|
+
byte_length: z16.number().int().nonnegative(),
|
|
2693
|
+
corrupted_path: z16.string()
|
|
2475
2694
|
});
|
|
2476
|
-
var
|
|
2695
|
+
var metaReconciledOnStartupEventSchema = z16.object({
|
|
2477
2696
|
...eventLedgerEnvelopeSchema,
|
|
2478
|
-
event_type:
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
new_marker: z18.literal("fabric:bootstrap"),
|
|
2483
|
-
timestamp: z18.string()
|
|
2484
|
-
});
|
|
2485
|
-
var metaReconciledOnStartupEventSchema = z18.object({
|
|
2486
|
-
...eventLedgerEnvelopeSchema,
|
|
2487
|
-
event_type: z18.literal("meta_reconciled_on_startup"),
|
|
2488
|
-
reconciled_files: z18.array(z18.string()),
|
|
2489
|
-
duration_ms: z18.number().int().nonnegative(),
|
|
2490
|
-
source: z18.literal("reconcileKnowledge")
|
|
2697
|
+
event_type: z16.literal("meta_reconciled_on_startup"),
|
|
2698
|
+
reconciled_files: z16.array(z16.string()),
|
|
2699
|
+
duration_ms: z16.number().int().nonnegative(),
|
|
2700
|
+
source: z16.literal("reconcileKnowledge")
|
|
2491
2701
|
});
|
|
2492
|
-
var metaReconciledEventSchema =
|
|
2702
|
+
var metaReconciledEventSchema = z16.object({
|
|
2493
2703
|
...eventLedgerEnvelopeSchema,
|
|
2494
|
-
event_type:
|
|
2495
|
-
reconciled_files:
|
|
2496
|
-
duration_ms:
|
|
2704
|
+
event_type: z16.literal("meta_reconciled"),
|
|
2705
|
+
reconciled_files: z16.array(z16.string()),
|
|
2706
|
+
duration_ms: z16.number().int().nonnegative(),
|
|
2497
2707
|
// v2.0.0-rc.23 TASK-005 (a-B): added `auto-heal-description` trigger so the
|
|
2498
2708
|
// read-path plan_context handler can drive a full reconcile when it detects
|
|
2499
2709
|
// any node carrying `description === undefined` (legacy meta drift that the
|
|
@@ -2507,7 +2717,7 @@ var metaReconciledEventSchema = z18.object({
|
|
|
2507
2717
|
// v2.0.0-rc.29 TASK-005 (BUG-G1): `auto-heal-after-drift` added so
|
|
2508
2718
|
// `ensureKnowledgeFresh` hot-path can chain a paired reconcile (closing the
|
|
2509
2719
|
// drift→heal gap) when the caller opts in via `autoHealOnDrift: true`.
|
|
2510
|
-
trigger:
|
|
2720
|
+
trigger: z16.enum([
|
|
2511
2721
|
"doctor",
|
|
2512
2722
|
"manual",
|
|
2513
2723
|
"auto-heal-description",
|
|
@@ -2515,195 +2725,207 @@ var metaReconciledEventSchema = z18.object({
|
|
|
2515
2725
|
"post-approve",
|
|
2516
2726
|
"post-modify"
|
|
2517
2727
|
]),
|
|
2518
|
-
source:
|
|
2728
|
+
source: z16.literal("reconcileKnowledge"),
|
|
2519
2729
|
// v2.0.0-rc.22 TASK-014 (Scope E): set when reconcileKnowledge forced a
|
|
2520
2730
|
// writeKnowledgeMeta on revision drift alone (no per-file content drift).
|
|
2521
2731
|
// Distinguishes top-level schema/revision repair from the standard per-file
|
|
2522
2732
|
// drift path. Optional so existing emitters stay unchanged.
|
|
2523
|
-
force_write_reason:
|
|
2733
|
+
force_write_reason: z16.enum(["revision_drift"]).optional()
|
|
2524
2734
|
});
|
|
2525
|
-
var claudeSkillPathMigratedEventSchema =
|
|
2735
|
+
var claudeSkillPathMigratedEventSchema = z16.object({
|
|
2526
2736
|
...eventLedgerEnvelopeSchema,
|
|
2527
|
-
event_type:
|
|
2528
|
-
from:
|
|
2529
|
-
to:
|
|
2737
|
+
event_type: z16.literal("claude_skill_path_migrated"),
|
|
2738
|
+
from: z16.string(),
|
|
2739
|
+
to: z16.string()
|
|
2530
2740
|
});
|
|
2531
|
-
var claudeHookPathMigratedEventSchema =
|
|
2741
|
+
var claudeHookPathMigratedEventSchema = z16.object({
|
|
2532
2742
|
...eventLedgerEnvelopeSchema,
|
|
2533
|
-
event_type:
|
|
2534
|
-
from:
|
|
2535
|
-
to:
|
|
2743
|
+
event_type: z16.literal("claude_hook_path_migrated"),
|
|
2744
|
+
from: z16.string(),
|
|
2745
|
+
to: z16.string()
|
|
2536
2746
|
});
|
|
2537
|
-
var codexSkillPathMigratedEventSchema =
|
|
2747
|
+
var codexSkillPathMigratedEventSchema = z16.object({
|
|
2538
2748
|
...eventLedgerEnvelopeSchema,
|
|
2539
|
-
event_type:
|
|
2540
|
-
from:
|
|
2541
|
-
to:
|
|
2749
|
+
event_type: z16.literal("codex_skill_path_migrated"),
|
|
2750
|
+
from: z16.string(),
|
|
2751
|
+
to: z16.string()
|
|
2542
2752
|
});
|
|
2543
|
-
var initScanCompletedEventSchema =
|
|
2753
|
+
var initScanCompletedEventSchema = z16.object({
|
|
2544
2754
|
...eventLedgerEnvelopeSchema,
|
|
2545
|
-
event_type:
|
|
2546
|
-
written_stable_ids:
|
|
2547
|
-
duration_ms:
|
|
2548
|
-
source:
|
|
2755
|
+
event_type: z16.literal("init_scan_completed"),
|
|
2756
|
+
written_stable_ids: z16.array(z16.string()),
|
|
2757
|
+
duration_ms: z16.number().int().nonnegative(),
|
|
2758
|
+
source: z16.enum(["init", "scan", "doctor_fix", "doctor-rescan"]).optional()
|
|
2549
2759
|
});
|
|
2550
|
-
var knowledgeProposedEventSchema =
|
|
2760
|
+
var knowledgeProposedEventSchema = z16.object({
|
|
2551
2761
|
...eventLedgerEnvelopeSchema,
|
|
2552
|
-
event_type:
|
|
2553
|
-
stable_id:
|
|
2554
|
-
timestamp:
|
|
2555
|
-
reason:
|
|
2762
|
+
event_type: z16.literal("knowledge_proposed"),
|
|
2763
|
+
stable_id: z16.string().optional(),
|
|
2764
|
+
timestamp: z16.string().datetime(),
|
|
2765
|
+
reason: z16.string().optional()
|
|
2556
2766
|
});
|
|
2557
|
-
var knowledgePromoteStartedEventSchema =
|
|
2767
|
+
var knowledgePromoteStartedEventSchema = z16.object({
|
|
2558
2768
|
...eventLedgerEnvelopeSchema,
|
|
2559
|
-
event_type:
|
|
2560
|
-
stable_id:
|
|
2561
|
-
timestamp:
|
|
2562
|
-
reason:
|
|
2769
|
+
event_type: z16.literal("knowledge_promote_started"),
|
|
2770
|
+
stable_id: z16.string().optional(),
|
|
2771
|
+
timestamp: z16.string().datetime(),
|
|
2772
|
+
reason: z16.string().optional()
|
|
2563
2773
|
});
|
|
2564
|
-
var knowledgePromotedEventSchema =
|
|
2774
|
+
var knowledgePromotedEventSchema = z16.object({
|
|
2565
2775
|
...eventLedgerEnvelopeSchema,
|
|
2566
|
-
event_type:
|
|
2567
|
-
stable_id:
|
|
2568
|
-
timestamp:
|
|
2569
|
-
reason:
|
|
2776
|
+
event_type: z16.literal("knowledge_promoted"),
|
|
2777
|
+
stable_id: z16.string().optional(),
|
|
2778
|
+
timestamp: z16.string().datetime(),
|
|
2779
|
+
reason: z16.string().optional()
|
|
2570
2780
|
});
|
|
2571
|
-
var knowledgePromoteFailedEventSchema =
|
|
2781
|
+
var knowledgePromoteFailedEventSchema = z16.object({
|
|
2572
2782
|
...eventLedgerEnvelopeSchema,
|
|
2573
|
-
event_type:
|
|
2574
|
-
stable_id:
|
|
2575
|
-
timestamp:
|
|
2576
|
-
reason:
|
|
2783
|
+
event_type: z16.literal("knowledge_promote_failed"),
|
|
2784
|
+
stable_id: z16.string().optional(),
|
|
2785
|
+
timestamp: z16.string().datetime(),
|
|
2786
|
+
reason: z16.string()
|
|
2577
2787
|
});
|
|
2578
|
-
var
|
|
2788
|
+
var knowledgeModifiedEventSchema = z16.object({
|
|
2789
|
+
...eventLedgerEnvelopeSchema,
|
|
2790
|
+
event_type: z16.literal("knowledge_modified"),
|
|
2791
|
+
stable_id: z16.string().optional(),
|
|
2792
|
+
timestamp: z16.string().datetime(),
|
|
2793
|
+
path: z16.string(),
|
|
2794
|
+
changed_fields: z16.array(z16.string()),
|
|
2795
|
+
before: z16.record(z16.unknown()),
|
|
2796
|
+
after: z16.record(z16.unknown()),
|
|
2797
|
+
reason: z16.string().optional()
|
|
2798
|
+
});
|
|
2799
|
+
var knowledgeLayerChangedEventSchema = z16.object({
|
|
2579
2800
|
...eventLedgerEnvelopeSchema,
|
|
2580
|
-
event_type:
|
|
2581
|
-
stable_id:
|
|
2582
|
-
timestamp:
|
|
2583
|
-
reason:
|
|
2584
|
-
from_layer:
|
|
2585
|
-
to_layer:
|
|
2801
|
+
event_type: z16.literal("knowledge_layer_changed"),
|
|
2802
|
+
stable_id: z16.string().optional(),
|
|
2803
|
+
timestamp: z16.string().datetime(),
|
|
2804
|
+
reason: z16.string().optional(),
|
|
2805
|
+
from_layer: z16.enum(["team", "personal"]),
|
|
2806
|
+
to_layer: z16.enum(["team", "personal"]),
|
|
2586
2807
|
// v2.0.0-rc.37 NEW-24: record the pre-flip stable_id so downstream consumers
|
|
2587
2808
|
// (fab_plan_context redirect surface, fab_get_knowledge_sections.redirect_to)
|
|
2588
2809
|
// can map a stale caller-held id back to the post-flip canonical id without
|
|
2589
2810
|
// requiring the caller to re-issue plan-context. Optional for forward-
|
|
2590
2811
|
// compatibility with rc ≤36 events that never carried this field.
|
|
2591
|
-
previous_stable_id:
|
|
2812
|
+
previous_stable_id: z16.string().optional()
|
|
2592
2813
|
});
|
|
2593
|
-
var knowledgeIdRedirectEventSchema =
|
|
2814
|
+
var knowledgeIdRedirectEventSchema = z16.object({
|
|
2594
2815
|
...eventLedgerEnvelopeSchema,
|
|
2595
|
-
event_type:
|
|
2596
|
-
timestamp:
|
|
2597
|
-
previous_stable_id:
|
|
2598
|
-
new_stable_id:
|
|
2599
|
-
reason:
|
|
2816
|
+
event_type: z16.literal("knowledge_id_redirect"),
|
|
2817
|
+
timestamp: z16.string().datetime(),
|
|
2818
|
+
previous_stable_id: z16.string(),
|
|
2819
|
+
new_stable_id: z16.string(),
|
|
2820
|
+
reason: z16.string().optional()
|
|
2600
2821
|
});
|
|
2601
|
-
var knowledgeSlugRenamedEventSchema =
|
|
2822
|
+
var knowledgeSlugRenamedEventSchema = z16.object({
|
|
2602
2823
|
...eventLedgerEnvelopeSchema,
|
|
2603
|
-
event_type:
|
|
2604
|
-
stable_id:
|
|
2605
|
-
timestamp:
|
|
2606
|
-
reason:
|
|
2607
|
-
from_slug:
|
|
2608
|
-
to_slug:
|
|
2609
|
-
});
|
|
2610
|
-
var knowledgeDemotedEventSchema =
|
|
2824
|
+
event_type: z16.literal("knowledge_slug_renamed"),
|
|
2825
|
+
stable_id: z16.string().optional(),
|
|
2826
|
+
timestamp: z16.string().datetime(),
|
|
2827
|
+
reason: z16.string().optional(),
|
|
2828
|
+
from_slug: z16.string(),
|
|
2829
|
+
to_slug: z16.string()
|
|
2830
|
+
});
|
|
2831
|
+
var knowledgeDemotedEventSchema = z16.object({
|
|
2611
2832
|
...eventLedgerEnvelopeSchema,
|
|
2612
|
-
event_type:
|
|
2613
|
-
stable_id:
|
|
2614
|
-
timestamp:
|
|
2615
|
-
reason:
|
|
2833
|
+
event_type: z16.literal("knowledge_demoted"),
|
|
2834
|
+
stable_id: z16.string().optional(),
|
|
2835
|
+
timestamp: z16.string().datetime(),
|
|
2836
|
+
reason: z16.string().optional()
|
|
2616
2837
|
});
|
|
2617
|
-
var knowledgeArchivedEventSchema =
|
|
2838
|
+
var knowledgeArchivedEventSchema = z16.object({
|
|
2618
2839
|
...eventLedgerEnvelopeSchema,
|
|
2619
|
-
event_type:
|
|
2620
|
-
stable_id:
|
|
2621
|
-
timestamp:
|
|
2622
|
-
reason:
|
|
2840
|
+
event_type: z16.literal("knowledge_archived"),
|
|
2841
|
+
stable_id: z16.string().optional(),
|
|
2842
|
+
timestamp: z16.string().datetime(),
|
|
2843
|
+
reason: z16.string().optional()
|
|
2623
2844
|
});
|
|
2624
|
-
var knowledgeArchiveAttemptedEventSchema =
|
|
2845
|
+
var knowledgeArchiveAttemptedEventSchema = z16.object({
|
|
2625
2846
|
...eventLedgerEnvelopeSchema,
|
|
2626
|
-
event_type:
|
|
2627
|
-
stable_id:
|
|
2628
|
-
timestamp:
|
|
2629
|
-
reason:
|
|
2847
|
+
event_type: z16.literal("knowledge_archive_attempted"),
|
|
2848
|
+
stable_id: z16.string().optional(),
|
|
2849
|
+
timestamp: z16.string().datetime(),
|
|
2850
|
+
reason: z16.string().optional()
|
|
2630
2851
|
});
|
|
2631
|
-
var knowledgeUnarchivedEventSchema =
|
|
2852
|
+
var knowledgeUnarchivedEventSchema = z16.object({
|
|
2632
2853
|
...eventLedgerEnvelopeSchema,
|
|
2633
|
-
event_type:
|
|
2634
|
-
stable_id:
|
|
2635
|
-
timestamp:
|
|
2636
|
-
reason:
|
|
2854
|
+
event_type: z16.literal("knowledge_unarchived"),
|
|
2855
|
+
stable_id: z16.string().optional(),
|
|
2856
|
+
timestamp: z16.string().datetime(),
|
|
2857
|
+
reason: z16.string().optional(),
|
|
2637
2858
|
// Pre-move archive path (e.g. ".fabric/.archive/decisions/KT-D-0007--single-cjs-hook.md").
|
|
2638
|
-
archive_path:
|
|
2639
|
-
// Post-move canonical path (e.g. "
|
|
2640
|
-
restored_to:
|
|
2859
|
+
archive_path: z16.string().optional(),
|
|
2860
|
+
// Post-move canonical path (e.g. "knowledge/decisions/KT-DEC-0007--single-cjs-hook.md" inside the resolved store).
|
|
2861
|
+
restored_to: z16.string().optional()
|
|
2641
2862
|
});
|
|
2642
|
-
var knowledgeDeferredEventSchema =
|
|
2863
|
+
var knowledgeDeferredEventSchema = z16.object({
|
|
2643
2864
|
...eventLedgerEnvelopeSchema,
|
|
2644
|
-
event_type:
|
|
2645
|
-
stable_id:
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2865
|
+
event_type: z16.literal("knowledge_deferred"),
|
|
2866
|
+
stable_id: z16.string().optional(),
|
|
2867
|
+
pending_path: z16.string().optional(),
|
|
2868
|
+
timestamp: z16.string().datetime(),
|
|
2869
|
+
reason: z16.string().optional(),
|
|
2870
|
+
until: z16.string().datetime().optional()
|
|
2871
|
+
});
|
|
2872
|
+
var knowledgeRejectedEventSchema = z16.object({
|
|
2651
2873
|
...eventLedgerEnvelopeSchema,
|
|
2652
|
-
event_type:
|
|
2653
|
-
stable_id:
|
|
2654
|
-
timestamp:
|
|
2655
|
-
reason:
|
|
2874
|
+
event_type: z16.literal("knowledge_rejected"),
|
|
2875
|
+
stable_id: z16.string().optional(),
|
|
2876
|
+
timestamp: z16.string().datetime(),
|
|
2877
|
+
reason: z16.string()
|
|
2656
2878
|
});
|
|
2657
|
-
var knowledgeConsumedEventSchema =
|
|
2879
|
+
var knowledgeConsumedEventSchema = z16.object({
|
|
2658
2880
|
...eventLedgerEnvelopeSchema,
|
|
2659
|
-
event_type:
|
|
2660
|
-
stable_id:
|
|
2661
|
-
consumed_at:
|
|
2662
|
-
client_hash:
|
|
2881
|
+
event_type: z16.literal("knowledge_consumed"),
|
|
2882
|
+
stable_id: z16.string(),
|
|
2883
|
+
consumed_at: z16.string().datetime(),
|
|
2884
|
+
client_hash: z16.string()
|
|
2663
2885
|
});
|
|
2664
|
-
var knowledgeScopeDegradedEventSchema =
|
|
2886
|
+
var knowledgeScopeDegradedEventSchema = z16.object({
|
|
2665
2887
|
...eventLedgerEnvelopeSchema,
|
|
2666
|
-
event_type:
|
|
2667
|
-
stable_id:
|
|
2668
|
-
timestamp:
|
|
2669
|
-
from_scope:
|
|
2670
|
-
to_scope:
|
|
2671
|
-
reason:
|
|
2672
|
-
});
|
|
2673
|
-
var doctorRunEventSchema =
|
|
2888
|
+
event_type: z16.literal("knowledge_scope_degraded"),
|
|
2889
|
+
stable_id: z16.string(),
|
|
2890
|
+
timestamp: z16.string().datetime(),
|
|
2891
|
+
from_scope: z16.enum(["narrow", "broad"]),
|
|
2892
|
+
to_scope: z16.enum(["narrow", "broad"]),
|
|
2893
|
+
reason: z16.string()
|
|
2894
|
+
});
|
|
2895
|
+
var doctorRunEventSchema = z16.object({
|
|
2674
2896
|
...eventLedgerEnvelopeSchema,
|
|
2675
|
-
event_type:
|
|
2676
|
-
mode:
|
|
2677
|
-
issues:
|
|
2678
|
-
mutations:
|
|
2679
|
-
timestamp:
|
|
2897
|
+
event_type: z16.literal("doctor_run"),
|
|
2898
|
+
mode: z16.enum(["lint", "fix-knowledge"]),
|
|
2899
|
+
issues: z16.number().int().nonnegative(),
|
|
2900
|
+
mutations: z16.number().int().nonnegative().optional(),
|
|
2901
|
+
timestamp: z16.string().datetime()
|
|
2680
2902
|
});
|
|
2681
|
-
var knowledgePathDangledEventSchema =
|
|
2903
|
+
var knowledgePathDangledEventSchema = z16.object({
|
|
2682
2904
|
...eventLedgerEnvelopeSchema,
|
|
2683
|
-
event_type:
|
|
2684
|
-
stable_id:
|
|
2685
|
-
removed_glob:
|
|
2905
|
+
event_type: z16.literal("knowledge_path_dangled"),
|
|
2906
|
+
stable_id: z16.string(),
|
|
2907
|
+
removed_glob: z16.string()
|
|
2686
2908
|
});
|
|
2687
|
-
var relevanceMigrationRunEventSchema =
|
|
2909
|
+
var relevanceMigrationRunEventSchema = z16.object({
|
|
2688
2910
|
...eventLedgerEnvelopeSchema,
|
|
2689
|
-
event_type:
|
|
2690
|
-
timestamp:
|
|
2691
|
-
scanned_count:
|
|
2692
|
-
touched_count:
|
|
2911
|
+
event_type: z16.literal("relevance_migration_run"),
|
|
2912
|
+
timestamp: z16.string().datetime(),
|
|
2913
|
+
scanned_count: z16.number().int().nonnegative(),
|
|
2914
|
+
touched_count: z16.number().int().nonnegative()
|
|
2693
2915
|
});
|
|
2694
|
-
var pendingAutoArchivedEventSchema =
|
|
2916
|
+
var pendingAutoArchivedEventSchema = z16.object({
|
|
2695
2917
|
...eventLedgerEnvelopeSchema,
|
|
2696
|
-
event_type:
|
|
2697
|
-
pending_path:
|
|
2698
|
-
archived_to:
|
|
2699
|
-
reason:
|
|
2918
|
+
event_type: z16.literal("pending_auto_archived"),
|
|
2919
|
+
pending_path: z16.string(),
|
|
2920
|
+
archived_to: z16.string(),
|
|
2921
|
+
reason: z16.string()
|
|
2700
2922
|
});
|
|
2701
|
-
var assistantTurnObservedEventSchema =
|
|
2923
|
+
var assistantTurnObservedEventSchema = z16.object({
|
|
2702
2924
|
...eventLedgerEnvelopeSchema,
|
|
2703
|
-
event_type:
|
|
2704
|
-
kb_line_raw:
|
|
2705
|
-
cite_ids:
|
|
2706
|
-
cite_tags:
|
|
2925
|
+
event_type: z16.literal("assistant_turn_observed"),
|
|
2926
|
+
kb_line_raw: z16.string().nullable(),
|
|
2927
|
+
cite_ids: z16.array(z16.string()).default([]),
|
|
2928
|
+
cite_tags: z16.array(citeTagSchema).default([]),
|
|
2707
2929
|
// v2.0.0-rc.24 TASK-01: per-cite contract commitments. Index-aligned with
|
|
2708
2930
|
// cite_ids/cite_tags (commitments[i] belongs to cite_ids[i]). Each slot
|
|
2709
2931
|
// carries `operators[]` (kind + glob target) or `skip_reason` when the cite
|
|
@@ -2711,15 +2933,15 @@ var assistantTurnObservedEventSchema = z18.object({
|
|
|
2711
2933
|
// empty array via `.default([])` and are excluded from contract-policy
|
|
2712
2934
|
// audits by the marker-gate (see cite_contract_policy_activated below).
|
|
2713
2935
|
// Mirrors the rc.20 cite_tags parallel-array evolution exactly.
|
|
2714
|
-
cite_commitments:
|
|
2715
|
-
|
|
2716
|
-
operators:
|
|
2717
|
-
|
|
2718
|
-
kind:
|
|
2719
|
-
target:
|
|
2936
|
+
cite_commitments: z16.array(
|
|
2937
|
+
z16.object({
|
|
2938
|
+
operators: z16.array(
|
|
2939
|
+
z16.object({
|
|
2940
|
+
kind: z16.enum(["edit", "not_edit", "require", "forbid"]),
|
|
2941
|
+
target: z16.string()
|
|
2720
2942
|
})
|
|
2721
2943
|
),
|
|
2722
|
-
skip_reason:
|
|
2944
|
+
skip_reason: z16.string().nullable()
|
|
2723
2945
|
})
|
|
2724
2946
|
).default([]),
|
|
2725
2947
|
// lifecycle-refactor W3-T4 (§2 store 轴 / store-qualified 观测): per-cite store
|
|
@@ -2729,174 +2951,183 @@ var assistantTurnObservedEventSchema = z18.object({
|
|
|
2729
2951
|
// doctor --cite-coverage can break compliance down per store WITHOUT joining
|
|
2730
2952
|
// against the store registry. Additive `.optional()` (NOT `.default([])`) so
|
|
2731
2953
|
// existing inline event constructors stay valid without supplying it — pre-W3-T4
|
|
2732
|
-
// events parse with the field absent and bucket under the
|
|
2733
|
-
cite_stores:
|
|
2734
|
-
client:
|
|
2735
|
-
turn_id:
|
|
2736
|
-
envelope_index:
|
|
2737
|
-
timestamp:
|
|
2738
|
-
});
|
|
2739
|
-
var citePolicyActivatedEventSchema =
|
|
2954
|
+
// events parse with the field absent and bucket under the unqualified default.
|
|
2955
|
+
cite_stores: z16.array(z16.string().nullable()).optional(),
|
|
2956
|
+
client: z16.enum(["cc", "codex"]).optional(),
|
|
2957
|
+
turn_id: z16.string(),
|
|
2958
|
+
envelope_index: z16.number().int().nonnegative().optional(),
|
|
2959
|
+
timestamp: z16.string().datetime()
|
|
2960
|
+
});
|
|
2961
|
+
var citePolicyActivatedEventSchema = z16.object({
|
|
2740
2962
|
...eventLedgerEnvelopeSchema,
|
|
2741
|
-
event_type:
|
|
2742
|
-
policy_version:
|
|
2743
|
-
timestamp:
|
|
2963
|
+
event_type: z16.literal("cite_policy_activated"),
|
|
2964
|
+
policy_version: z16.string(),
|
|
2965
|
+
timestamp: z16.string().datetime()
|
|
2744
2966
|
});
|
|
2745
|
-
var citeContractPolicyActivatedEventSchema =
|
|
2967
|
+
var citeContractPolicyActivatedEventSchema = z16.object({
|
|
2746
2968
|
...eventLedgerEnvelopeSchema,
|
|
2747
|
-
event_type:
|
|
2969
|
+
event_type: z16.literal("cite_contract_policy_activated")
|
|
2748
2970
|
});
|
|
2749
|
-
var eventsRotatedEventSchema =
|
|
2971
|
+
var eventsRotatedEventSchema = z16.object({
|
|
2750
2972
|
...eventLedgerEnvelopeSchema,
|
|
2751
|
-
event_type:
|
|
2752
|
-
cutoff_ts:
|
|
2753
|
-
archived_count:
|
|
2754
|
-
kept_count:
|
|
2755
|
-
archive_path:
|
|
2973
|
+
event_type: z16.literal("events_rotated"),
|
|
2974
|
+
cutoff_ts: z16.string().datetime(),
|
|
2975
|
+
archived_count: z16.number().int().nonnegative(),
|
|
2976
|
+
kept_count: z16.number().int().nonnegative(),
|
|
2977
|
+
archive_path: z16.string()
|
|
2756
2978
|
});
|
|
2757
|
-
var knowledgeMetaAutoHealedEventSchema =
|
|
2979
|
+
var knowledgeMetaAutoHealedEventSchema = z16.object({
|
|
2758
2980
|
...eventLedgerEnvelopeSchema,
|
|
2759
|
-
event_type:
|
|
2760
|
-
previous_revision_hash:
|
|
2761
|
-
revision_hash:
|
|
2762
|
-
trigger:
|
|
2763
|
-
caller:
|
|
2981
|
+
event_type: z16.literal("knowledge_meta_auto_healed"),
|
|
2982
|
+
previous_revision_hash: z16.string(),
|
|
2983
|
+
revision_hash: z16.string(),
|
|
2984
|
+
trigger: z16.literal("read"),
|
|
2985
|
+
caller: z16.enum(["planContext", "getKnowledgeSections", "getKnowledge", "extractKnowledge"]).optional()
|
|
2764
2986
|
});
|
|
2765
|
-
var serveLockClearedEventSchema =
|
|
2987
|
+
var serveLockClearedEventSchema = z16.object({
|
|
2766
2988
|
...eventLedgerEnvelopeSchema,
|
|
2767
|
-
event_type:
|
|
2768
|
-
pid:
|
|
2769
|
-
age_ms:
|
|
2770
|
-
timestamp:
|
|
2989
|
+
event_type: z16.literal("serve_lock_cleared"),
|
|
2990
|
+
pid: z16.number().int().nonnegative(),
|
|
2991
|
+
age_ms: z16.number().int().nonnegative(),
|
|
2992
|
+
timestamp: z16.string().datetime()
|
|
2771
2993
|
});
|
|
2772
|
-
var knowledgeEnrichedEventSchema =
|
|
2994
|
+
var knowledgeEnrichedEventSchema = z16.object({
|
|
2773
2995
|
...eventLedgerEnvelopeSchema,
|
|
2774
|
-
event_type:
|
|
2775
|
-
path:
|
|
2776
|
-
added_fields:
|
|
2777
|
-
mode:
|
|
2778
|
-
timestamp:
|
|
2996
|
+
event_type: z16.literal("knowledge_enriched"),
|
|
2997
|
+
path: z16.string(),
|
|
2998
|
+
added_fields: z16.array(z16.enum(["intent_clues", "tech_stack", "impact", "must_read_if"])),
|
|
2999
|
+
mode: z16.enum(["auto", "preview", "readonly", "interactive"]),
|
|
3000
|
+
timestamp: z16.string().datetime()
|
|
2779
3001
|
});
|
|
2780
|
-
var sessionArchiveAttemptedEventSchema =
|
|
3002
|
+
var sessionArchiveAttemptedEventSchema = z16.object({
|
|
2781
3003
|
...eventLedgerEnvelopeSchema,
|
|
2782
|
-
event_type:
|
|
2783
|
-
outcome:
|
|
2784
|
-
covered_through_ts:
|
|
2785
|
-
candidates_proposed:
|
|
2786
|
-
knowledge_proposed_ids:
|
|
3004
|
+
event_type: z16.literal("session_archive_attempted"),
|
|
3005
|
+
outcome: z16.enum(["proposed", "viability_failed", "user_dismissed", "skipped_no_signal"]),
|
|
3006
|
+
covered_through_ts: z16.number().int().nonnegative(),
|
|
3007
|
+
candidates_proposed: z16.number().int().nonnegative().default(0),
|
|
3008
|
+
knowledge_proposed_ids: z16.array(z16.string()).default([])
|
|
2787
3009
|
});
|
|
2788
|
-
var hookSurfaceEmittedEventSchema =
|
|
3010
|
+
var hookSurfaceEmittedEventSchema = z16.object({
|
|
2789
3011
|
...eventLedgerEnvelopeSchema,
|
|
2790
|
-
event_type:
|
|
2791
|
-
hook_name:
|
|
2792
|
-
client:
|
|
2793
|
-
target_channel:
|
|
2794
|
-
rendered_ids:
|
|
2795
|
-
delivery_status:
|
|
2796
|
-
suppression_reason:
|
|
2797
|
-
});
|
|
2798
|
-
var hookSignalEmittedEventSchema =
|
|
3012
|
+
event_type: z16.literal("hook_surface_emitted"),
|
|
3013
|
+
hook_name: z16.string(),
|
|
3014
|
+
client: z16.enum(["cc", "codex"]),
|
|
3015
|
+
target_channel: z16.string(),
|
|
3016
|
+
rendered_ids: z16.array(z16.string()),
|
|
3017
|
+
delivery_status: z16.enum(["delivered", "suppressed", "error"]),
|
|
3018
|
+
suppression_reason: z16.string().optional()
|
|
3019
|
+
});
|
|
3020
|
+
var hookSignalEmittedEventSchema = z16.object({
|
|
2799
3021
|
...eventLedgerEnvelopeSchema,
|
|
2800
|
-
event_type:
|
|
2801
|
-
signal_type:
|
|
2802
|
-
threshold:
|
|
2803
|
-
actual_value:
|
|
2804
|
-
fired:
|
|
3022
|
+
event_type: z16.literal("hook_signal_emitted"),
|
|
3023
|
+
signal_type: z16.enum(["archive", "review", "maintenance", "other"]),
|
|
3024
|
+
threshold: z16.number(),
|
|
3025
|
+
actual_value: z16.number(),
|
|
3026
|
+
fired: z16.boolean()
|
|
2805
3027
|
});
|
|
2806
|
-
var mcpStdioTraceEventSchema =
|
|
3028
|
+
var mcpStdioTraceEventSchema = z16.object({
|
|
2807
3029
|
...eventLedgerEnvelopeSchema,
|
|
2808
|
-
event_type:
|
|
2809
|
-
tool_name:
|
|
2810
|
-
request_id:
|
|
2811
|
-
duration_ms:
|
|
2812
|
-
status:
|
|
2813
|
-
payload_bytes_in:
|
|
2814
|
-
payload_bytes_out:
|
|
2815
|
-
error_code:
|
|
2816
|
-
});
|
|
2817
|
-
var payloadGuardObservedEventSchema =
|
|
3030
|
+
event_type: z16.literal("mcp_stdio_trace"),
|
|
3031
|
+
tool_name: z16.string(),
|
|
3032
|
+
request_id: z16.string(),
|
|
3033
|
+
duration_ms: z16.number().nonnegative(),
|
|
3034
|
+
status: z16.enum(["ok", "error"]),
|
|
3035
|
+
payload_bytes_in: z16.number().int().nonnegative(),
|
|
3036
|
+
payload_bytes_out: z16.number().int().nonnegative(),
|
|
3037
|
+
error_code: z16.string().optional()
|
|
3038
|
+
});
|
|
3039
|
+
var payloadGuardObservedEventSchema = z16.object({
|
|
2818
3040
|
...eventLedgerEnvelopeSchema,
|
|
2819
|
-
event_type:
|
|
2820
|
-
tool_name:
|
|
2821
|
-
path_count:
|
|
2822
|
-
tokens_estimated:
|
|
2823
|
-
truncated:
|
|
2824
|
-
cap:
|
|
2825
|
-
});
|
|
2826
|
-
var skillInvocationStartedEventSchema =
|
|
3041
|
+
event_type: z16.literal("payload_guard_observed"),
|
|
3042
|
+
tool_name: z16.string(),
|
|
3043
|
+
path_count: z16.number().int().nonnegative(),
|
|
3044
|
+
tokens_estimated: z16.number().int().nonnegative(),
|
|
3045
|
+
truncated: z16.boolean(),
|
|
3046
|
+
cap: z16.number().int().positive()
|
|
3047
|
+
});
|
|
3048
|
+
var skillInvocationStartedEventSchema = z16.object({
|
|
2827
3049
|
...eventLedgerEnvelopeSchema,
|
|
2828
|
-
event_type:
|
|
2829
|
-
skill_name:
|
|
2830
|
-
trigger_source:
|
|
2831
|
-
entry_point:
|
|
3050
|
+
event_type: z16.literal("skill_invocation_started"),
|
|
3051
|
+
skill_name: z16.string(),
|
|
3052
|
+
trigger_source: z16.enum(["user", "auto_invoke", "ai_self_trigger", "chained"]),
|
|
3053
|
+
entry_point: z16.string()
|
|
2832
3054
|
});
|
|
2833
|
-
var skillInvocationCompletedEventSchema =
|
|
3055
|
+
var skillInvocationCompletedEventSchema = z16.object({
|
|
2834
3056
|
...eventLedgerEnvelopeSchema,
|
|
2835
|
-
event_type:
|
|
2836
|
-
skill_name:
|
|
2837
|
-
trigger_source:
|
|
2838
|
-
entry_point:
|
|
2839
|
-
outcome:
|
|
2840
|
-
elapsed_ms:
|
|
2841
|
-
});
|
|
2842
|
-
var skillPhaseTransitionEventSchema =
|
|
3057
|
+
event_type: z16.literal("skill_invocation_completed"),
|
|
3058
|
+
skill_name: z16.string(),
|
|
3059
|
+
trigger_source: z16.enum(["user", "auto_invoke", "ai_self_trigger", "chained"]),
|
|
3060
|
+
entry_point: z16.string(),
|
|
3061
|
+
outcome: z16.enum(["completed", "aborted", "error", "no_op"]),
|
|
3062
|
+
elapsed_ms: z16.number().nonnegative().optional()
|
|
3063
|
+
});
|
|
3064
|
+
var skillPhaseTransitionEventSchema = z16.object({
|
|
2843
3065
|
...eventLedgerEnvelopeSchema,
|
|
2844
|
-
event_type:
|
|
2845
|
-
skill_name:
|
|
2846
|
-
phase:
|
|
2847
|
-
status:
|
|
2848
|
-
checkpoint:
|
|
2849
|
-
elapsed_ms:
|
|
2850
|
-
});
|
|
2851
|
-
var skillTriggerCandidateEventSchema =
|
|
3066
|
+
event_type: z16.literal("skill_phase_transition"),
|
|
3067
|
+
skill_name: z16.string(),
|
|
3068
|
+
phase: z16.string(),
|
|
3069
|
+
status: z16.enum(["entered", "completed", "skipped", "failed"]),
|
|
3070
|
+
checkpoint: z16.string().optional(),
|
|
3071
|
+
elapsed_ms: z16.number().nonnegative().optional()
|
|
3072
|
+
});
|
|
3073
|
+
var skillTriggerCandidateEventSchema = z16.object({
|
|
2852
3074
|
...eventLedgerEnvelopeSchema,
|
|
2853
|
-
event_type:
|
|
2854
|
-
skill_name:
|
|
2855
|
-
trigger_source:
|
|
2856
|
-
signal:
|
|
2857
|
-
invoked:
|
|
3075
|
+
event_type: z16.literal("skill_trigger_candidate"),
|
|
3076
|
+
skill_name: z16.string(),
|
|
3077
|
+
trigger_source: z16.enum(["user", "auto_invoke", "ai_self_trigger", "chained"]),
|
|
3078
|
+
signal: z16.string(),
|
|
3079
|
+
invoked: z16.boolean()
|
|
2858
3080
|
});
|
|
2859
|
-
var llmJudgeRunEventSchema =
|
|
3081
|
+
var llmJudgeRunEventSchema = z16.object({
|
|
2860
3082
|
...eventLedgerEnvelopeSchema,
|
|
2861
|
-
event_type:
|
|
2862
|
-
prompt:
|
|
2863
|
-
version:
|
|
2864
|
-
model:
|
|
2865
|
-
input_trace_id:
|
|
2866
|
-
score:
|
|
2867
|
-
rationale:
|
|
2868
|
-
});
|
|
2869
|
-
var clientCapabilitySnapshotEventSchema =
|
|
3083
|
+
event_type: z16.literal("llm_judge_run"),
|
|
3084
|
+
prompt: z16.string(),
|
|
3085
|
+
version: z16.string(),
|
|
3086
|
+
model: z16.string(),
|
|
3087
|
+
input_trace_id: z16.string(),
|
|
3088
|
+
score: z16.number(),
|
|
3089
|
+
rationale: z16.string()
|
|
3090
|
+
});
|
|
3091
|
+
var clientCapabilitySnapshotEventSchema = z16.object({
|
|
2870
3092
|
...eventLedgerEnvelopeSchema,
|
|
2871
|
-
event_type:
|
|
2872
|
-
client:
|
|
2873
|
-
capabilities:
|
|
2874
|
-
version:
|
|
3093
|
+
event_type: z16.literal("client_capability_snapshot"),
|
|
3094
|
+
client: z16.enum(["cc", "codex"]),
|
|
3095
|
+
capabilities: z16.array(z16.string()),
|
|
3096
|
+
version: z16.string()
|
|
2875
3097
|
});
|
|
2876
|
-
var sessionEndedEventSchema =
|
|
3098
|
+
var sessionEndedEventSchema = z16.object({
|
|
2877
3099
|
...eventLedgerEnvelopeSchema,
|
|
2878
|
-
event_type:
|
|
3100
|
+
event_type: z16.literal("session_ended")
|
|
2879
3101
|
});
|
|
2880
|
-
var fileMutatedEventSchema =
|
|
3102
|
+
var fileMutatedEventSchema = z16.object({
|
|
3103
|
+
...eventLedgerEnvelopeSchema,
|
|
3104
|
+
event_type: z16.literal("file_mutated"),
|
|
3105
|
+
path: z16.string(),
|
|
3106
|
+
tool_call_id: z16.string(),
|
|
3107
|
+
tool_name: z16.string().optional(),
|
|
3108
|
+
source_event_id: z16.string().optional(),
|
|
3109
|
+
store_id: z16.string().optional()
|
|
3110
|
+
});
|
|
3111
|
+
var knowledgeBodyReadEventSchema = z16.object({
|
|
2881
3112
|
...eventLedgerEnvelopeSchema,
|
|
2882
|
-
event_type:
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
});
|
|
2889
|
-
var precompactObservedEventSchema =
|
|
3113
|
+
event_type: z16.literal("knowledge_body_read"),
|
|
3114
|
+
stable_id: z16.string(),
|
|
3115
|
+
store: z16.string().optional(),
|
|
3116
|
+
path: z16.string(),
|
|
3117
|
+
tool_call_id: z16.string().optional(),
|
|
3118
|
+
tool_name: z16.string().optional()
|
|
3119
|
+
});
|
|
3120
|
+
var precompactObservedEventSchema = z16.object({
|
|
2890
3121
|
...eventLedgerEnvelopeSchema,
|
|
2891
|
-
event_type:
|
|
3122
|
+
event_type: z16.literal("precompact_observed")
|
|
2892
3123
|
});
|
|
2893
|
-
var graphEdgeCandidateRequestedEventSchema =
|
|
3124
|
+
var graphEdgeCandidateRequestedEventSchema = z16.object({
|
|
2894
3125
|
...eventLedgerEnvelopeSchema,
|
|
2895
|
-
event_type:
|
|
2896
|
-
stable_id:
|
|
2897
|
-
store:
|
|
3126
|
+
event_type: z16.literal("graph_edge_candidate_requested"),
|
|
3127
|
+
stable_id: z16.string(),
|
|
3128
|
+
store: z16.string().optional()
|
|
2898
3129
|
});
|
|
2899
|
-
var eventLedgerEventSchema =
|
|
3130
|
+
var eventLedgerEventSchema = z16.discriminatedUnion("event_type", [
|
|
2900
3131
|
knowledgeContextPlannedEventSchema,
|
|
2901
3132
|
knowledgeSelectionEventSchema,
|
|
2902
3133
|
knowledgeSectionsFetchedEventSchema,
|
|
@@ -2906,10 +3137,6 @@ var eventLedgerEventSchema = z18.discriminatedUnion("event_type", [
|
|
|
2906
3137
|
reapplyCompletedEventSchema,
|
|
2907
3138
|
installDiffAppliedEventSchema,
|
|
2908
3139
|
eventLedgerTruncatedEventSchema,
|
|
2909
|
-
mcpConfigMigratedEventSchema,
|
|
2910
|
-
// v2.0.0-rc.19 TASK-004: bootstrap_marker_migrated — one-time fabric:knowledge-base
|
|
2911
|
-
// → fabric:bootstrap marker rewrite emitted per file by `fabric doctor --fix`.
|
|
2912
|
-
bootstrapMarkerMigratedEventSchema,
|
|
2913
3140
|
metaReconciledOnStartupEventSchema,
|
|
2914
3141
|
metaReconciledEventSchema,
|
|
2915
3142
|
claudeSkillPathMigratedEventSchema,
|
|
@@ -2921,6 +3148,7 @@ var eventLedgerEventSchema = z18.discriminatedUnion("event_type", [
|
|
|
2921
3148
|
knowledgePromoteStartedEventSchema,
|
|
2922
3149
|
knowledgePromotedEventSchema,
|
|
2923
3150
|
knowledgePromoteFailedEventSchema,
|
|
3151
|
+
knowledgeModifiedEventSchema,
|
|
2924
3152
|
knowledgeLayerChangedEventSchema,
|
|
2925
3153
|
// v2.0.0-rc.37 NEW-24: dedicated old→new stable_id mapping event
|
|
2926
3154
|
knowledgeIdRedirectEventSchema,
|
|
@@ -2992,6 +3220,9 @@ var eventLedgerEventSchema = z18.discriminatedUnion("event_type", [
|
|
|
2992
3220
|
// lifecycle-refactor Wave 2 — dormant-hook activation markers.
|
|
2993
3221
|
sessionEndedEventSchema,
|
|
2994
3222
|
fileMutatedEventSchema,
|
|
3223
|
+
// KT-DEC-0030: knowledge_body_read — PostToolUse native-Read consumption marker
|
|
3224
|
+
// (replaces knowledge_consumed as the funnel's "body opened" signal).
|
|
3225
|
+
knowledgeBodyReadEventSchema,
|
|
2995
3226
|
precompactObservedEventSchema,
|
|
2996
3227
|
graphEdgeCandidateRequestedEventSchema
|
|
2997
3228
|
]);
|
|
@@ -3031,19 +3262,24 @@ var PROFILES = {
|
|
|
3031
3262
|
topK: 12,
|
|
3032
3263
|
payloadWarnBytes: 8192,
|
|
3033
3264
|
payloadHardBytes: 32768,
|
|
3034
|
-
injectionChars: 1e3
|
|
3265
|
+
injectionChars: 1e3,
|
|
3266
|
+
bodyBudgetBytes: 2048
|
|
3035
3267
|
},
|
|
3036
3268
|
balanced: {
|
|
3037
3269
|
topK: 24,
|
|
3038
3270
|
payloadWarnBytes: 16384,
|
|
3039
3271
|
payloadHardBytes: 65536,
|
|
3040
|
-
injectionChars: 2e3
|
|
3272
|
+
injectionChars: 2e3,
|
|
3273
|
+
// grill-report C-009: ~4KB ≈ 1~3 typical bodies. Independent of the 16KB
|
|
3274
|
+
// payloadWarnBytes (the response cap), small on purpose — see field doc.
|
|
3275
|
+
bodyBudgetBytes: 4096
|
|
3041
3276
|
},
|
|
3042
3277
|
generous: {
|
|
3043
3278
|
topK: 48,
|
|
3044
3279
|
payloadWarnBytes: 32768,
|
|
3045
3280
|
payloadHardBytes: 131072,
|
|
3046
|
-
injectionChars: 4e3
|
|
3281
|
+
injectionChars: 4e3,
|
|
3282
|
+
bodyBudgetBytes: 8192
|
|
3047
3283
|
}
|
|
3048
3284
|
};
|
|
3049
3285
|
var DEFAULT_RETRIEVAL_BUDGET_PROFILE = "balanced";
|
|
@@ -3053,7 +3289,8 @@ function resolveRetrievalBudget(overrides) {
|
|
|
3053
3289
|
topK: overrides?.topK ?? base.topK,
|
|
3054
3290
|
payloadWarnBytes: overrides?.payloadWarnBytes ?? base.payloadWarnBytes,
|
|
3055
3291
|
payloadHardBytes: overrides?.payloadHardBytes ?? base.payloadHardBytes,
|
|
3056
|
-
injectionChars: overrides?.injectionChars ?? base.injectionChars
|
|
3292
|
+
injectionChars: overrides?.injectionChars ?? base.injectionChars,
|
|
3293
|
+
bodyBudgetBytes: overrides?.bodyBudgetBytes ?? base.bodyBudgetBytes
|
|
3057
3294
|
};
|
|
3058
3295
|
}
|
|
3059
3296
|
function retrievalBudgetProfile(profile) {
|
|
@@ -3061,10 +3298,11 @@ function retrievalBudgetProfile(profile) {
|
|
|
3061
3298
|
}
|
|
3062
3299
|
export {
|
|
3063
3300
|
AGENTS_META_IDENTITY_SOURCES,
|
|
3064
|
-
AGENTS_META_LAYERS,
|
|
3065
3301
|
AGENTS_META_TOPOLOGY_TYPES,
|
|
3066
3302
|
AgentsMetaCountersSchema,
|
|
3067
|
-
|
|
3303
|
+
BOOTSTRAP_CANONICAL_BY_LOCALE,
|
|
3304
|
+
BOOTSTRAP_CANONICAL_EN,
|
|
3305
|
+
BOOTSTRAP_CANONICAL_ZH,
|
|
3068
3306
|
BOOTSTRAP_MARKER_BEGIN,
|
|
3069
3307
|
BOOTSTRAP_MARKER_END,
|
|
3070
3308
|
BOOTSTRAP_REGEX,
|
|
@@ -3084,9 +3322,6 @@ export {
|
|
|
3084
3322
|
KNOWN_SCOPE_PREFIXES,
|
|
3085
3323
|
KnowledgeEntryFrontmatterSchema,
|
|
3086
3324
|
KnowledgeTypeSchema,
|
|
3087
|
-
LEGACY_KB_MARKER_BEGIN,
|
|
3088
|
-
LEGACY_KB_MARKER_END,
|
|
3089
|
-
LEGACY_KB_REGEX,
|
|
3090
3325
|
LayerSchema,
|
|
3091
3326
|
MCP_STORE_AWARE_CONTRACTS,
|
|
3092
3327
|
MCP_STORE_AWARE_TOOLS,
|
|
@@ -3098,16 +3333,18 @@ export {
|
|
|
3098
3333
|
PERSONAL_SCOPE,
|
|
3099
3334
|
PERSONAL_STORE_SENTINEL,
|
|
3100
3335
|
PROJECT_ROOT_SIGNALS,
|
|
3101
|
-
|
|
3336
|
+
PROPOSED_REASON_DESCRIPTIONS_BY_LOCALE,
|
|
3102
3337
|
PROTECTED_TOKENS,
|
|
3103
3338
|
ProposedReasonSchema,
|
|
3104
3339
|
REDACTION_PLACEHOLDER_PREFIX,
|
|
3105
|
-
ResolverNotImplementedError,
|
|
3106
3340
|
SCOPE_COORDINATE_PATTERN,
|
|
3107
3341
|
STORES_ROOT_DIR,
|
|
3342
|
+
STORE_ALIAS_PATTERN,
|
|
3108
3343
|
STORE_GITIGNORE,
|
|
3109
3344
|
STORE_KNOWLEDGE_TYPE_DIRS,
|
|
3110
3345
|
STORE_LAYOUT,
|
|
3346
|
+
STORE_MOUNT_GROUPS,
|
|
3347
|
+
STORE_MOUNT_NAME_PATTERN,
|
|
3111
3348
|
STORE_PENDING_DIR,
|
|
3112
3349
|
STORE_PROJECT_ID_PATTERN,
|
|
3113
3350
|
STORE_RESOLVER_WARNING_CODES,
|
|
@@ -3117,7 +3354,6 @@ export {
|
|
|
3117
3354
|
addMountedStore,
|
|
3118
3355
|
addStoreProject,
|
|
3119
3356
|
agentsIdentitySourceSchema,
|
|
3120
|
-
agentsLayerSchema,
|
|
3121
3357
|
agentsMetaNodeSchema,
|
|
3122
3358
|
agentsMetaSchema,
|
|
3123
3359
|
agentsTopologyTypeSchema,
|
|
@@ -3133,7 +3369,6 @@ export {
|
|
|
3133
3369
|
auditModeSchema,
|
|
3134
3370
|
bindRequiredStore,
|
|
3135
3371
|
bindingsSnapshotPath,
|
|
3136
|
-
bootstrapMarkerMigratedEventSchema,
|
|
3137
3372
|
buildDebugBundle,
|
|
3138
3373
|
buildFailureTrace,
|
|
3139
3374
|
buildScanRecommendations,
|
|
@@ -3156,11 +3391,12 @@ export {
|
|
|
3156
3391
|
defaultLayerFilterSchema,
|
|
3157
3392
|
defaultMessages,
|
|
3158
3393
|
deriveAgentsMetaIdentitySource,
|
|
3159
|
-
deriveAgentsMetaLayer,
|
|
3160
3394
|
deriveAgentsMetaStableId,
|
|
3161
3395
|
deriveAgentsMetaTopologyType,
|
|
3396
|
+
deriveMountLabel,
|
|
3162
3397
|
detachMountedStore,
|
|
3163
3398
|
detectNodeLocale,
|
|
3399
|
+
disambiguateAlias,
|
|
3164
3400
|
doctorRunEventSchema,
|
|
3165
3401
|
driftDetectedEventSchema,
|
|
3166
3402
|
editIntentCheckedEventSchema,
|
|
@@ -3220,6 +3456,7 @@ export {
|
|
|
3220
3456
|
isPersonalScope,
|
|
3221
3457
|
knowledgeArchiveAttemptedEventSchema,
|
|
3222
3458
|
knowledgeArchivedEventSchema,
|
|
3459
|
+
knowledgeBodyReadEventSchema,
|
|
3223
3460
|
knowledgeConsumedEventSchema,
|
|
3224
3461
|
knowledgeContextPlannedEventSchema,
|
|
3225
3462
|
knowledgeDeferredEventSchema,
|
|
@@ -3229,6 +3466,7 @@ export {
|
|
|
3229
3466
|
knowledgeIdRedirectEventSchema,
|
|
3230
3467
|
knowledgeLayerChangedEventSchema,
|
|
3231
3468
|
knowledgeMetaAutoHealedEventSchema,
|
|
3469
|
+
knowledgeModifiedEventSchema,
|
|
3232
3470
|
knowledgePathDangledEventSchema,
|
|
3233
3471
|
knowledgePromoteFailedEventSchema,
|
|
3234
3472
|
knowledgePromoteStartedEventSchema,
|
|
@@ -3259,7 +3497,7 @@ export {
|
|
|
3259
3497
|
localKnowledgeIdSchema,
|
|
3260
3498
|
lockApprovedEventSchema,
|
|
3261
3499
|
lockDriftEventSchema,
|
|
3262
|
-
|
|
3500
|
+
matchBootstrapCanonicalLocale,
|
|
3263
3501
|
mcpEventLedgerEventSchema,
|
|
3264
3502
|
mcpPayloadLimitsSchema,
|
|
3265
3503
|
mcpStdioTraceEventSchema,
|
|
@@ -3269,6 +3507,8 @@ export {
|
|
|
3269
3507
|
mountedStoreSchema,
|
|
3270
3508
|
normalizeCiteTag,
|
|
3271
3509
|
normalizeLocale,
|
|
3510
|
+
nudgeModeSchema,
|
|
3511
|
+
observeConfigSchema,
|
|
3272
3512
|
onboardSlotSchema,
|
|
3273
3513
|
parityCapabilitySchema,
|
|
3274
3514
|
parityClientExpectationSchema,
|
|
@@ -3300,6 +3540,7 @@ export {
|
|
|
3300
3540
|
readSetGoldenFileSchema,
|
|
3301
3541
|
readStoreCounters,
|
|
3302
3542
|
readStoreIdentity,
|
|
3543
|
+
readStoreIdentityAsync,
|
|
3303
3544
|
readStoreProjects,
|
|
3304
3545
|
reapplyCompletedEventSchema,
|
|
3305
3546
|
recallAnnotations,
|
|
@@ -3307,14 +3548,18 @@ export {
|
|
|
3307
3548
|
recallOutputSchema,
|
|
3308
3549
|
recognizeStoreDir,
|
|
3309
3550
|
reconcileStoreCounters,
|
|
3551
|
+
redactPii,
|
|
3310
3552
|
redactSecrets,
|
|
3311
3553
|
relevanceMigrationRunEventSchema,
|
|
3312
3554
|
requiredStoreEntrySchema,
|
|
3555
|
+
resolveBootstrapCanonical,
|
|
3313
3556
|
resolveCandidates,
|
|
3314
3557
|
resolveFabricLocale,
|
|
3558
|
+
resolveGlobalLocale,
|
|
3315
3559
|
resolveGlobalRoot,
|
|
3316
3560
|
resolveRetrievalBudget,
|
|
3317
3561
|
resolveStoreQualifiedId,
|
|
3562
|
+
resolveWorkspaceBindingId,
|
|
3318
3563
|
resolvedBindingsSnapshotSchema,
|
|
3319
3564
|
retrievalBudgetProfile,
|
|
3320
3565
|
ruleDescriptionIndexItemSchema,
|
|
@@ -3333,16 +3578,21 @@ export {
|
|
|
3333
3578
|
skillInvocationStartedEventSchema,
|
|
3334
3579
|
skillPhaseTransitionEventSchema,
|
|
3335
3580
|
skillTriggerCandidateEventSchema,
|
|
3581
|
+
storeAliasSchema,
|
|
3336
3582
|
storeAwareEntrySchema,
|
|
3337
3583
|
storeCountersPath,
|
|
3338
3584
|
storeCountersSchema,
|
|
3339
3585
|
storeHasProject,
|
|
3340
3586
|
storeIdentitySchema,
|
|
3341
3587
|
storeKnowledgeTypeDir,
|
|
3588
|
+
storeMountGroup,
|
|
3589
|
+
storeMountNameSchema,
|
|
3590
|
+
storeMountSubPath,
|
|
3342
3591
|
storeProjectSchema,
|
|
3343
3592
|
storeProjectsFileSchema,
|
|
3344
3593
|
storeReadSetSchema,
|
|
3345
3594
|
storeRelativePath,
|
|
3595
|
+
storeRelativePathForMount,
|
|
3346
3596
|
storeResolveInputSchema,
|
|
3347
3597
|
storeResolverWarningCodeSchema,
|
|
3348
3598
|
storeResolverWarningSchema,
|
|
@@ -3352,6 +3602,7 @@ export {
|
|
|
3352
3602
|
uidSchema,
|
|
3353
3603
|
withDerivedAgentsMetaNodeDefaults,
|
|
3354
3604
|
writeBindingsSnapshot,
|
|
3605
|
+
writeRouteSchema,
|
|
3355
3606
|
writeTargetSchema,
|
|
3356
3607
|
writtenToStoreSchema,
|
|
3357
3608
|
zhCNMessages
|