@fenglimg/fabric-shared 2.2.0-rc.4 → 2.2.0-rc.9
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-AQMDXC6J.js} +400 -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-D_gT1CEA.d.ts} +83 -34
- package/dist/index.d.ts +488 -579
- package/dist/index.js +1265 -1068
- 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,60 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
BOOTSTRAP_CANONICAL_BY_LOCALE,
|
|
3
|
+
BOOTSTRAP_CANONICAL_EN,
|
|
4
|
+
BOOTSTRAP_CANONICAL_ZH,
|
|
3
5
|
BOOTSTRAP_MARKER_BEGIN,
|
|
4
6
|
BOOTSTRAP_MARKER_END,
|
|
5
7
|
BOOTSTRAP_REGEX,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from "./chunk-AFT7DB4P.js";
|
|
8
|
+
matchBootstrapCanonicalLocale,
|
|
9
|
+
resolveBootstrapCanonical
|
|
10
|
+
} from "./chunk-BDJQIOQO.js";
|
|
10
11
|
import {
|
|
11
12
|
PROTECTED_TOKENS,
|
|
12
13
|
createTranslator,
|
|
13
14
|
defaultMessages,
|
|
14
|
-
detectNodeLocale,
|
|
15
15
|
enMessages,
|
|
16
|
-
normalizeLocale,
|
|
17
16
|
resolveFabricLocale,
|
|
18
17
|
zhCNMessages
|
|
19
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-AQMDXC6J.js";
|
|
19
|
+
import {
|
|
20
|
+
GLOBAL_BINDINGS_DIR,
|
|
21
|
+
GLOBAL_STATE_DIR,
|
|
22
|
+
PERSONAL_STORE_SENTINEL,
|
|
23
|
+
STORES_ROOT_DIR,
|
|
24
|
+
STORE_ALIAS_PATTERN,
|
|
25
|
+
STORE_KNOWLEDGE_TYPE_DIRS,
|
|
26
|
+
STORE_LAYOUT,
|
|
27
|
+
STORE_MOUNT_GROUPS,
|
|
28
|
+
STORE_MOUNT_NAME_PATTERN,
|
|
29
|
+
STORE_PROJECT_ID_PATTERN,
|
|
30
|
+
STORE_UUID_PATTERN,
|
|
31
|
+
deriveMountLabel,
|
|
32
|
+
detectNodeLocale,
|
|
33
|
+
globalConfigPath,
|
|
34
|
+
globalConfigSchema,
|
|
35
|
+
loadGlobalConfig,
|
|
36
|
+
mountedStoreSchema,
|
|
37
|
+
normalizeLocale,
|
|
38
|
+
requiredStoreEntrySchema,
|
|
39
|
+
resolveGlobalLocale,
|
|
40
|
+
resolveGlobalRoot,
|
|
41
|
+
saveGlobalConfig,
|
|
42
|
+
storeAliasSchema,
|
|
43
|
+
storeIdentitySchema,
|
|
44
|
+
storeKnowledgeTypeDir,
|
|
45
|
+
storeMountGroup,
|
|
46
|
+
storeMountNameSchema,
|
|
47
|
+
storeMountSubPath,
|
|
48
|
+
storeProjectSchema,
|
|
49
|
+
storeProjectsFileSchema,
|
|
50
|
+
storeRelativePath,
|
|
51
|
+
storeRelativePathForMount,
|
|
52
|
+
storeUuidSchema
|
|
53
|
+
} from "./chunk-2GLIAZ5M.js";
|
|
20
54
|
import {
|
|
21
55
|
atomicWriteJson,
|
|
22
56
|
withFileLock
|
|
23
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-C7WZPYZE.js";
|
|
24
58
|
import {
|
|
25
59
|
FabExtractKnowledgeInputSchema,
|
|
26
60
|
FabExtractKnowledgeInputShape,
|
|
@@ -30,14 +64,17 @@ import {
|
|
|
30
64
|
FabReviewOutputSchema,
|
|
31
65
|
FabReviewOutputShape,
|
|
32
66
|
KNOWLEDGE_TYPE_CODES,
|
|
67
|
+
KNOWN_SCOPE_PREFIXES,
|
|
33
68
|
KnowledgeEntryFrontmatterSchema,
|
|
34
69
|
KnowledgeTypeSchema,
|
|
35
70
|
LayerSchema,
|
|
36
71
|
MaturitySchema,
|
|
37
72
|
ONBOARD_SLOT_NAMES,
|
|
38
73
|
ONBOARD_SLOT_TOTAL,
|
|
39
|
-
|
|
74
|
+
PERSONAL_SCOPE,
|
|
75
|
+
PROPOSED_REASON_DESCRIPTIONS_BY_LOCALE,
|
|
40
76
|
ProposedReasonSchema,
|
|
77
|
+
SCOPE_COORDINATE_PATTERN,
|
|
41
78
|
StableIdSchema,
|
|
42
79
|
annotateIntentRequestSchema,
|
|
43
80
|
archiveScanAnnotations,
|
|
@@ -46,12 +83,14 @@ import {
|
|
|
46
83
|
citeContractMetricsSchema,
|
|
47
84
|
citeCoverageReportSchema,
|
|
48
85
|
citeLayerTypeBreakdownSchema,
|
|
86
|
+
entryScopeMetadataSchema,
|
|
49
87
|
fabExtractKnowledgeAnnotations,
|
|
50
88
|
fabReviewAnnotations,
|
|
51
89
|
formatKnowledgeId,
|
|
52
90
|
historyStateQuerySchema,
|
|
53
91
|
humanLockApproveRequestSchema,
|
|
54
92
|
humanLockFileParamsSchema,
|
|
93
|
+
isPersonalScope,
|
|
55
94
|
knowledgeSectionsAnnotations,
|
|
56
95
|
knowledgeSectionsInputSchema,
|
|
57
96
|
knowledgeSectionsOutputSchema,
|
|
@@ -67,8 +106,10 @@ import {
|
|
|
67
106
|
recallAnnotations,
|
|
68
107
|
recallInputSchema,
|
|
69
108
|
recallOutputSchema,
|
|
109
|
+
scopeCoordinateSchema,
|
|
110
|
+
scopeRoot,
|
|
70
111
|
structuredWarningSchema
|
|
71
|
-
} from "./chunk-
|
|
112
|
+
} from "./chunk-5AKCRBKJ.js";
|
|
72
113
|
import "./chunk-LXNCAKJZ.js";
|
|
73
114
|
|
|
74
115
|
// src/schemas/agents-meta.ts
|
|
@@ -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()
|
|
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()
|
|
364
357
|
}).strict();
|
|
365
|
-
var
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
var
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
id: z5.string().min(1),
|
|
379
|
-
suggested_remote: z5.union([z5.string().min(1), z5.literal(PERSONAL_STORE_SENTINEL)]).optional()
|
|
380
|
-
}).strict();
|
|
381
|
-
var STORE_KNOWLEDGE_TYPE_DIRS = [
|
|
382
|
-
"models",
|
|
383
|
-
"decisions",
|
|
384
|
-
"guidelines",
|
|
385
|
-
"pitfalls",
|
|
386
|
-
"processes"
|
|
387
|
-
];
|
|
388
|
-
var STORE_LAYOUT = {
|
|
389
|
-
identityFile: "store.json",
|
|
390
|
-
// Store-internal project registry (W1/A2). Committed parallel to store.json.
|
|
391
|
-
projectsFile: "projects.json",
|
|
392
|
-
// v2.2 W4 (agents.meta decolo) — per-store monotonic stable_id counters.
|
|
393
|
-
// COMMITTED parallel to store.json/projects.json (NOT gitignored like the
|
|
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,25 @@ 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:
|
|
705
|
-
//
|
|
706
|
-
//
|
|
707
|
-
//
|
|
708
|
-
//
|
|
709
|
-
//
|
|
710
|
-
//
|
|
711
|
-
|
|
639
|
+
hint_broad_top_k: z5.number().int().min(1).max(50).optional().default(8),
|
|
640
|
+
// KT-DEC-0036: the SessionStart broad-menu is now index-only (title + summary
|
|
641
|
+
// per always-active entry, no eager body), so the former `hint_broad_budget_chars`
|
|
642
|
+
// body char-budget knob was retired — there is no rendered body left to bound.
|
|
643
|
+
// W4-1 (KT-DEC-0028 / KT-MOD-0001): scale backstop for the FULL broad index.
|
|
644
|
+
// After W2-1 retired the hint_broad_top_k hard cap, the broad banner shows
|
|
645
|
+
// every broad entry (completeness); this is the only guard — once a store's
|
|
646
|
+
// rendered broad index exceeds this many lines the overflow tail folds into a
|
|
647
|
+
// single drift marker. The doctor `broad-index-drift` lint (W4-2) warns at 80%
|
|
648
|
+
// of this value per store so the corpus can be pruned (fabric-audit) BEFORE the
|
|
649
|
+
// banner silently truncates. Default 50; range 20..500 (read inline by
|
|
650
|
+
// knowledge-hint-broad.cjs#readBroadIndexBackstop with the same bounds).
|
|
651
|
+
broad_index_backstop: z5.number().int().min(20).max(500).optional().default(50),
|
|
712
652
|
// v2.0.0-rc.37 NEW-16: durable per-signal dismiss for the fabric-hint Stop
|
|
713
653
|
// hook nudges. Any signal type listed here is suppressed at emit time across
|
|
714
654
|
// all sessions (the session-scoped sibling lives in a .fabric/.cache sidecar
|
|
715
655
|
// written on request). Mirrors the cite_evict_interval=0 opt-out convention —
|
|
716
656
|
// a knob for an existing surface, not a new feature. Unknown types ignored.
|
|
717
|
-
hint_dismiss_signals:
|
|
657
|
+
hint_dismiss_signals: z5.array(z5.enum(["archive", "review", "import", "maintenance"])).optional(),
|
|
718
658
|
// v2.1 ADJ-NEWN-4: user-override escape hatches for the two strong behavioral
|
|
719
659
|
// policies (cite-before-edit + self-archive). The strong policies can make an
|
|
720
660
|
// agent feel like a "stubborn parrot" (D2 user-in-control red line); these
|
|
@@ -726,15 +666,15 @@ var fabricConfigSchema = z6.object({
|
|
|
726
666
|
// surface, mirroring the cite_evict_interval=0 / hint_dismiss_signals opt-out
|
|
727
667
|
// convention, NOT a new feature. Wave3 J32 will quantify the friction these
|
|
728
668
|
// relieve; until then they ship as inert-safe opt-outs.
|
|
729
|
-
cite_policy_enabled:
|
|
730
|
-
self_archive_policy_enabled:
|
|
669
|
+
cite_policy_enabled: z5.boolean().optional().default(true),
|
|
670
|
+
self_archive_policy_enabled: z5.boolean().optional().default(true),
|
|
731
671
|
// v2.0.0-rc.33 W2-1 (P0-9): TopK upper bound for the narrow PreToolUse hint
|
|
732
672
|
// emitted by knowledge-hint-narrow.cjs. After filtering to entries whose
|
|
733
673
|
// `relevance_scope === "narrow"` (rc.27 TASK-005 audit §2.5 fix), the hook
|
|
734
674
|
// slices to this many before the E3 emit-gate / renderSummary pipeline.
|
|
735
675
|
// Default 5 keeps each per-Edit hint terse — five lines max so the agent's
|
|
736
676
|
// working memory is not displaced by an unwieldy banner. Range 1..20.
|
|
737
|
-
hint_narrow_top_k:
|
|
677
|
+
hint_narrow_top_k: z5.number().int().min(1).max(20).optional().default(5),
|
|
738
678
|
// v2.0.0-rc.33 W2-1 (P0-9): per-file dedup window (in PreToolUse turns) for
|
|
739
679
|
// the narrow hint. Same (file_path, stable_id) tuple stays silent for this
|
|
740
680
|
// many turns even when the E3 cross-session cache would otherwise re-emit.
|
|
@@ -744,7 +684,7 @@ var fabricConfigSchema = z6.object({
|
|
|
744
684
|
// Storage: .fabric/.cache/narrow-dedup-window.json — distinct from session-
|
|
745
685
|
// hints cache so a window-only suppression does not poison cross-session
|
|
746
686
|
// dedupe semantics.
|
|
747
|
-
hint_narrow_dedup_window_turns:
|
|
687
|
+
hint_narrow_dedup_window_turns: z5.number().int().min(1).max(50).optional().default(5),
|
|
748
688
|
// v2.0.0-rc.33 W2-5 (P1-8): cooldown between broad SessionStart hint emits,
|
|
749
689
|
// in hours. Distinct from the archive_hint_cooldown_hours that gates the
|
|
750
690
|
// fabric-hint Stop hook — knowledge-hint-broad re-fires on every
|
|
@@ -753,14 +693,14 @@ var fabricConfigSchema = z6.object({
|
|
|
753
693
|
// menu at most once per hour"; 0 means "no cooldown, current behavior."
|
|
754
694
|
// Range 0..168 (one week). Stored alongside fabric-hint's cooldown cache
|
|
755
695
|
// under a distinct knowledge-hint-broad key.
|
|
756
|
-
hint_broad_cooldown_hours:
|
|
696
|
+
hint_broad_cooldown_hours: z5.number().int().min(0).max(168).optional().default(0),
|
|
757
697
|
// v2.0.0-rc.33 W2-5 (P1-8): cooldown for the narrow PreToolUse hint.
|
|
758
698
|
// Same shape as hint_broad_cooldown_hours but applies to per-Edit hint
|
|
759
699
|
// re-emission across the cooldown window — independent of E3 session-
|
|
760
700
|
// hints dedupe. Default 0 preserves rc.32 behavior; set to e.g. 1 to
|
|
761
701
|
// throttle hint frequency during rapid-fire editing sprints. Range
|
|
762
702
|
// 0..168 (one week).
|
|
763
|
-
hint_narrow_cooldown_hours:
|
|
703
|
+
hint_narrow_cooldown_hours: z5.number().int().min(0).max(168).optional().default(0),
|
|
764
704
|
// v2.0.0-rc.33 W4-B3 (T5 P2): per-maturity inactivity thresholds (days)
|
|
765
705
|
// driving orphan_demote. Hardcoded at proven=90/verified=30/draft=14 in
|
|
766
706
|
// rc.32; chatty workspaces want them tighter, slow ones want them looser.
|
|
@@ -768,26 +708,19 @@ var fabricConfigSchema = z6.object({
|
|
|
768
708
|
// chosen so a typo can't accidentally disable the lint (min 1).
|
|
769
709
|
//
|
|
770
710
|
// 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(),
|
|
711
|
+
// draft/verified/proven (KT-DEC-0005). These threshold keys use the canonical
|
|
712
|
+
// vocabulary; the loader maps proven→stable / verified→endorsed onto the
|
|
713
|
+
// doctor's internal orphan_demote ladder.
|
|
714
|
+
orphan_demote_proven_days: z5.number().int().min(1).max(3650).optional(),
|
|
715
|
+
orphan_demote_verified_days: z5.number().int().min(1).max(3650).optional(),
|
|
716
|
+
orphan_demote_draft_days: z5.number().int().min(1).max(3650).optional(),
|
|
784
717
|
// v2.0.0-rc.33 W4-A3 (T4 P2): per-entry summary truncation length used by
|
|
785
718
|
// knowledge-hint-{broad,narrow}.cjs. Hard-coded at 80 chars in rc.32 — too
|
|
786
719
|
// short for entries with parameterized summaries (e.g. "Use bcrypt with
|
|
787
720
|
// cost=12 for password hashing"), too long for terse pitfalls. Range 40..240;
|
|
788
721
|
// default 80 preserves rc.32 behavior. Both hooks read the same key so the
|
|
789
722
|
// banner styling stays consistent across SessionStart + PreToolUse.
|
|
790
|
-
hint_summary_max_len:
|
|
723
|
+
hint_summary_max_len: z5.number().int().min(40).max(240).optional().default(80),
|
|
791
724
|
// v2.0.0-rc.33 W2-6 (P0-7 + P0-8): when true, knowledge-hint hooks emit
|
|
792
725
|
// their banners as `hookSpecificOutput.additionalContext` JSON on stdout
|
|
793
726
|
// (per Claude Code PreToolUse hook contract — see
|
|
@@ -797,7 +730,7 @@ var fabricConfigSchema = z6.object({
|
|
|
797
730
|
// coverage focus (rc.32 baseline 3.1% → primary cause: reminders never
|
|
798
731
|
// entered model context). Set false to revert to legacy stderr-only mode
|
|
799
732
|
// for hosts that don't honor the JSON contract.
|
|
800
|
-
hint_reminder_to_context:
|
|
733
|
+
hint_reminder_to_context: z5.boolean().optional().default(true),
|
|
801
734
|
// v2.0.0-rc.29 TASK-008 (BUG-F3): selection-token TTL override. The
|
|
802
735
|
// `fab_plan_context` MCP tool hands clients a `selection_token` whose default
|
|
803
736
|
// 5-minute lifetime (`SELECTION_TOKEN_TTL_MS` at
|
|
@@ -818,26 +751,28 @@ var fabricConfigSchema = z6.object({
|
|
|
818
751
|
// applied after BM25 ranking. Absent → library default (24). See
|
|
819
752
|
// planContextTopKSchema for the range/calibration rationale.
|
|
820
753
|
plan_context_top_k: planContextTopKSchema.optional(),
|
|
821
|
-
//
|
|
822
|
-
//
|
|
823
|
-
//
|
|
824
|
-
//
|
|
825
|
-
//
|
|
826
|
-
//
|
|
827
|
-
|
|
828
|
-
|
|
754
|
+
// KT-DEC-0038: ratio-to-top relevance floor (α) for recall / plan_context.
|
|
755
|
+
// After ranking, keep only candidates whose fused score >= α × the top
|
|
756
|
+
// candidate's score — self-normalizing against the current query's max, so it
|
|
757
|
+
// is immune to BM25's uncalibrated cross-query scale. top_k is a pure safety
|
|
758
|
+
// cap above this. Range 0..1; absent → library default (0.25). 0 disables the
|
|
759
|
+
// floor (keep all up to top_k).
|
|
760
|
+
recall_relevance_ratio: z5.number().min(0).max(1).optional(),
|
|
761
|
+
// KT-DEC-0037: the `retrieval_budget_profile` enum was deleted. top_k is the
|
|
762
|
+
// sole retrieval knob (plan_context_top_k above); payload limits pass through
|
|
763
|
+
// explicit `mcpPayloadLimits`, else the fixed PAYLOAD_LIMIT_DEFAULT_* guardrail.
|
|
829
764
|
// v2.2 C2-vector (W2-T7): OPTIONAL dense-embedding semantic retrieval, layered
|
|
830
765
|
// as a recall supplement after BM25. Default OFF (`--no-embed` is the baseline);
|
|
831
766
|
// requires the operator to install the optional `fastembed` package — absent →
|
|
832
767
|
// text-only fallback. Never grows the default install footprint.
|
|
833
|
-
embed_enabled:
|
|
768
|
+
embed_enabled: z5.boolean().optional().default(false),
|
|
834
769
|
// Weight applied to the 0..1 cosine similarity before it joins the additive
|
|
835
770
|
// score. Capped at 49 — strictly BELOW BM25_WEIGHT (50) — so a perfect vector
|
|
836
771
|
// match (weight × 1) can never outscore a single strong BM25 term match. This
|
|
837
772
|
// ENFORCES the "vectors supplement, never override lexical relevance"
|
|
838
773
|
// invariant in the schema rather than leaving it to a comment (W2-REVIEW codex
|
|
839
774
|
// MED-4). Range 0..49; default 30.
|
|
840
|
-
embed_weight:
|
|
775
|
+
embed_weight: z5.number().int().min(0).max(49).optional().default(30),
|
|
841
776
|
// v2.1 ③ vector-chinese-model (P3): which fastembed model to load. The prior
|
|
842
777
|
// code pinned fastembed's English default (bge-small-en-v1.5) — wrong for the
|
|
843
778
|
// Chinese-heavy zh-CN-hybrid KB. Values are the fastembed@2.x EmbeddingModel
|
|
@@ -847,7 +782,7 @@ var fabricConfigSchema = z6.object({
|
|
|
847
782
|
// available for full multilingual recall at a ~1GB download + slower CPU cost.
|
|
848
783
|
// (V1 research: fastembed@2.1.0 has NO multilingual-e5-SMALL — the originally
|
|
849
784
|
// planned pin — so bge-small-zh is the light Chinese choice.)
|
|
850
|
-
embed_model:
|
|
785
|
+
embed_model: z5.enum([
|
|
851
786
|
"fast-bge-small-zh-v1.5",
|
|
852
787
|
"fast-multilingual-e5-large",
|
|
853
788
|
"fast-bge-small-en-v1.5",
|
|
@@ -859,8 +794,8 @@ var fabricConfigSchema = z6.object({
|
|
|
859
794
|
});
|
|
860
795
|
|
|
861
796
|
// src/schemas/fabric-config-introspect.ts
|
|
862
|
-
import { z as
|
|
863
|
-
var positiveIntSchema =
|
|
797
|
+
import { z as z6 } from "zod";
|
|
798
|
+
var positiveIntSchema = z6.coerce.number().int().positive();
|
|
864
799
|
function makePositiveIntField(key, defaultValue) {
|
|
865
800
|
return {
|
|
866
801
|
key,
|
|
@@ -916,6 +851,28 @@ function makeEnumField(key, group, enumValues, defaultValue) {
|
|
|
916
851
|
}
|
|
917
852
|
};
|
|
918
853
|
}
|
|
854
|
+
function makeBooleanField(key, defaultValue) {
|
|
855
|
+
return {
|
|
856
|
+
key,
|
|
857
|
+
group: "D_behavior",
|
|
858
|
+
widget: "select",
|
|
859
|
+
label_i18n_key: `cli.config.fields.${key}.label`,
|
|
860
|
+
description_i18n_key: `cli.config.fields.${key}.description`,
|
|
861
|
+
default: String(defaultValue),
|
|
862
|
+
enum_values: ["true", "false"],
|
|
863
|
+
validate(raw) {
|
|
864
|
+
const trimmed = raw.trim();
|
|
865
|
+
if (trimmed === "true") return { ok: true, value: true };
|
|
866
|
+
if (trimmed === "false") return { ok: true, value: false };
|
|
867
|
+
return { ok: false, error: "Must be one of: true, false." };
|
|
868
|
+
},
|
|
869
|
+
format_for_display(value) {
|
|
870
|
+
if (typeof value === "boolean") return String(value);
|
|
871
|
+
if (value === void 0 || value === null) return String(defaultValue);
|
|
872
|
+
return String(value);
|
|
873
|
+
}
|
|
874
|
+
};
|
|
875
|
+
}
|
|
919
876
|
var SCHEMA_DEFAULTS = fabricConfigSchema.parse({});
|
|
920
877
|
function pickNumberDefault(key) {
|
|
921
878
|
const v = SCHEMA_DEFAULTS[key];
|
|
@@ -944,12 +901,13 @@ function getPanelFieldByKey(key) {
|
|
|
944
901
|
}
|
|
945
902
|
var PANEL_FIELDS = [
|
|
946
903
|
// --- Group A: Locale (2) ---
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
904
|
+
// grill-6fixes (D1): `fabric_language` is no longer a project-config field —
|
|
905
|
+
// it is the single machine-wide tone in `~/.fabric/fabric-global.json`. The
|
|
906
|
+
// panel still surfaces it (the `fabric config` language entry), but config.ts
|
|
907
|
+
// special-cases this key to read/write the GLOBAL config instead of the
|
|
908
|
+
// project file. Default is a literal "en" since there is no project-schema
|
|
909
|
+
// default to derive from.
|
|
910
|
+
makeEnumField("fabric_language", "A_locale", fabricLanguageSchema.options, "en"),
|
|
953
911
|
makeEnumField(
|
|
954
912
|
"default_layer_filter",
|
|
955
913
|
"A_locale",
|
|
@@ -993,39 +951,23 @@ var PANEL_FIELDS = [
|
|
|
993
951
|
"C_audit",
|
|
994
952
|
auditModeSchema.options,
|
|
995
953
|
AUDIT_MODE_PANEL_DEFAULT
|
|
996
|
-
)
|
|
954
|
+
),
|
|
955
|
+
// --- Group D: Behavior / features (2) ---
|
|
956
|
+
// nudge_mode — the master switch for the human-visible nudge experience
|
|
957
|
+
// (the most user-facing runtime knob, previously JSON-only). embed_enabled —
|
|
958
|
+
// vector semantic recall, panel-editable now that config lives in `.fabric`
|
|
959
|
+
// (A1); enabling also needs the host-side `fabric install --enable-embed`.
|
|
960
|
+
makeEnumField("nudge_mode", "D_behavior", nudgeModeSchema.options, "normal"),
|
|
961
|
+
makeBooleanField("embed_enabled", false)
|
|
997
962
|
];
|
|
998
963
|
|
|
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
964
|
// src/schemas/store-stable-id.ts
|
|
1023
|
-
import { z as
|
|
965
|
+
import { z as z7 } from "zod";
|
|
1024
966
|
var localKnowledgeIdSchema = StableIdSchema;
|
|
1025
967
|
var UID_SEGMENT_PATTERN = /^[a-z0-9-]+$/u;
|
|
1026
|
-
var uidSchema =
|
|
968
|
+
var uidSchema = z7.string().min(1).regex(UID_SEGMENT_PATTERN, "uid must be lowercase [a-z0-9-] segments");
|
|
1027
969
|
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 =
|
|
970
|
+
var globalRefSchema = z7.string().regex(GLOBAL_REF_PATTERN, "global_ref must be <store_uuid>[:<uid>]:<local_id>");
|
|
1029
971
|
function formatGlobalRef(parts) {
|
|
1030
972
|
const { store_uuid, uid, local_id } = parts;
|
|
1031
973
|
return uid === void 0 ? `${store_uuid}:${local_id}` : `${store_uuid}:${uid}:${local_id}`;
|
|
@@ -1050,14 +992,14 @@ function parseGlobalRef(ref) {
|
|
|
1050
992
|
local_id
|
|
1051
993
|
};
|
|
1052
994
|
}
|
|
1053
|
-
var storeKnowledgeTypeCountersSchema =
|
|
1054
|
-
MOD:
|
|
1055
|
-
DEC:
|
|
1056
|
-
GLD:
|
|
1057
|
-
PIT:
|
|
1058
|
-
PRO:
|
|
995
|
+
var storeKnowledgeTypeCountersSchema = z7.object({
|
|
996
|
+
MOD: z7.number().int().nonnegative().default(0),
|
|
997
|
+
DEC: z7.number().int().nonnegative().default(0),
|
|
998
|
+
GLD: z7.number().int().nonnegative().default(0),
|
|
999
|
+
PIT: z7.number().int().nonnegative().default(0),
|
|
1000
|
+
PRO: z7.number().int().nonnegative().default(0)
|
|
1059
1001
|
}).default({ MOD: 0, DEC: 0, GLD: 0, PIT: 0, PRO: 0 });
|
|
1060
|
-
var storeCountersSchema =
|
|
1002
|
+
var storeCountersSchema = z7.object({
|
|
1061
1003
|
KP: storeKnowledgeTypeCountersSchema,
|
|
1062
1004
|
KT: storeKnowledgeTypeCountersSchema
|
|
1063
1005
|
}).default({
|
|
@@ -1066,64 +1008,63 @@ var storeCountersSchema = z9.object({
|
|
|
1066
1008
|
});
|
|
1067
1009
|
|
|
1068
1010
|
// src/schemas/parity-matrix.ts
|
|
1069
|
-
import { z as
|
|
1070
|
-
var PARITY_CLIENTS = ["claudeCode", "codexCLI"
|
|
1071
|
-
var parityClientSchema =
|
|
1011
|
+
import { z as z8 } from "zod";
|
|
1012
|
+
var PARITY_CLIENTS = ["claudeCode", "codexCLI"];
|
|
1013
|
+
var parityClientSchema = z8.enum(PARITY_CLIENTS);
|
|
1072
1014
|
var PARITY_SURFACES = ["skill", "hook", "mcp", "render"];
|
|
1073
|
-
var paritySurfaceSchema =
|
|
1074
|
-
var parityClientExpectationSchema =
|
|
1075
|
-
supported:
|
|
1076
|
-
mechanism:
|
|
1077
|
-
notes:
|
|
1015
|
+
var paritySurfaceSchema = z8.enum(PARITY_SURFACES);
|
|
1016
|
+
var parityClientExpectationSchema = z8.object({
|
|
1017
|
+
supported: z8.boolean(),
|
|
1018
|
+
mechanism: z8.string().optional(),
|
|
1019
|
+
notes: z8.string().optional()
|
|
1078
1020
|
}).strict();
|
|
1079
|
-
var parityCapabilitySchema =
|
|
1080
|
-
id:
|
|
1021
|
+
var parityCapabilitySchema = z8.object({
|
|
1022
|
+
id: z8.string().min(1),
|
|
1081
1023
|
surface: paritySurfaceSchema,
|
|
1082
|
-
description:
|
|
1083
|
-
clients:
|
|
1024
|
+
description: z8.string().min(1),
|
|
1025
|
+
clients: z8.object({
|
|
1084
1026
|
claudeCode: parityClientExpectationSchema,
|
|
1085
|
-
codexCLI: parityClientExpectationSchema
|
|
1086
|
-
cursor: parityClientExpectationSchema
|
|
1027
|
+
codexCLI: parityClientExpectationSchema
|
|
1087
1028
|
}).strict()
|
|
1088
1029
|
}).strict();
|
|
1089
|
-
var parityMatrixSchema =
|
|
1030
|
+
var parityMatrixSchema = z8.object({
|
|
1090
1031
|
// Schema/version tag of the matrix document itself.
|
|
1091
|
-
version:
|
|
1032
|
+
version: z8.string().min(1),
|
|
1092
1033
|
// Free-form note on what release/milestone this matrix targets.
|
|
1093
|
-
generated_for:
|
|
1094
|
-
capabilities:
|
|
1034
|
+
generated_for: z8.string().min(1),
|
|
1035
|
+
capabilities: z8.array(parityCapabilitySchema).min(1)
|
|
1095
1036
|
}).strict();
|
|
1096
1037
|
|
|
1097
1038
|
// src/resolver/contracts.ts
|
|
1098
|
-
import { z as
|
|
1039
|
+
import { z as z9 } from "zod";
|
|
1099
1040
|
var PROJECT_ROOT_SIGNALS = ["env", "marker", "cwd", "repo"];
|
|
1100
|
-
var projectRootSignalSchema =
|
|
1101
|
-
var projectRootSignalsSchema =
|
|
1041
|
+
var projectRootSignalSchema = z9.enum(PROJECT_ROOT_SIGNALS);
|
|
1042
|
+
var projectRootSignalsSchema = z9.object({
|
|
1102
1043
|
// FABRIC_PROJECT_ROOT, if set.
|
|
1103
|
-
env:
|
|
1044
|
+
env: z9.string().optional(),
|
|
1104
1045
|
// Nearest directory AT-OR-ABOVE cwd holding `.fabric/fabric-config.json`,
|
|
1105
1046
|
// if any (the upward marker search result; may equal cwd).
|
|
1106
|
-
markerDir:
|
|
1047
|
+
markerDir: z9.string().optional(),
|
|
1107
1048
|
// Always present — the process cwd.
|
|
1108
|
-
cwd:
|
|
1049
|
+
cwd: z9.string().min(1),
|
|
1109
1050
|
// git repo root, if inside a repo.
|
|
1110
|
-
repoRoot:
|
|
1051
|
+
repoRoot: z9.string().optional(),
|
|
1111
1052
|
// The `project_id` read from the winning root's fabric-config.json during
|
|
1112
1053
|
// (fs) signal collection. The pure resolver echoes it — it cannot invent a
|
|
1113
1054
|
// UUID. Worktrees of one repo share the committed config, hence the same
|
|
1114
1055
|
// project_id (S45 merge). Absent when no .fabric config exists at the root
|
|
1115
1056
|
// yet (fresh repo-fallback) → resolution still yields the root with a null
|
|
1116
1057
|
// projectId so the caller can mint+persist one at install time.
|
|
1117
|
-
discoveredProjectId:
|
|
1058
|
+
discoveredProjectId: z9.string().optional()
|
|
1118
1059
|
}).strict();
|
|
1119
|
-
var projectRootResolutionSchema =
|
|
1060
|
+
var projectRootResolutionSchema = z9.object({
|
|
1120
1061
|
// Absolute project root directory.
|
|
1121
|
-
projectRoot:
|
|
1062
|
+
projectRoot: z9.string().min(1),
|
|
1122
1063
|
// Stable project identity. One repo = one .fabric = one project_id (S32);
|
|
1123
1064
|
// git worktrees of the same repo resolve to the SAME project_id (S45).
|
|
1124
1065
|
// Null when the resolved root has no fabric-config.json yet (fresh
|
|
1125
1066
|
// repo-fallback) — the caller mints + persists a UUID at install time.
|
|
1126
|
-
projectId:
|
|
1067
|
+
projectId: z9.string().min(1).nullable(),
|
|
1127
1068
|
// Which signal won.
|
|
1128
1069
|
signalUsed: projectRootSignalSchema
|
|
1129
1070
|
}).strict();
|
|
@@ -1132,91 +1073,96 @@ var STORE_RESOLVER_WARNING_CODES = [
|
|
|
1132
1073
|
// required_stores entry has no matching mounted store (S51)
|
|
1133
1074
|
"local_only_no_remote",
|
|
1134
1075
|
// mounted but local-only (R5#5 nudge, non-fatal)
|
|
1135
|
-
"alias_unresolved"
|
|
1076
|
+
"alias_unresolved",
|
|
1136
1077
|
// referenced alias maps to no mounted store
|
|
1078
|
+
"missing_write_route"
|
|
1079
|
+
// multi/shared write requires an explicit route
|
|
1137
1080
|
];
|
|
1138
|
-
var storeResolverWarningCodeSchema =
|
|
1139
|
-
var storeResolverWarningSchema =
|
|
1081
|
+
var storeResolverWarningCodeSchema = z9.enum(STORE_RESOLVER_WARNING_CODES);
|
|
1082
|
+
var storeResolverWarningSchema = z9.object({
|
|
1140
1083
|
code: storeResolverWarningCodeSchema,
|
|
1141
1084
|
// The alias/UUID/id the warning concerns.
|
|
1142
|
-
ref:
|
|
1143
|
-
message:
|
|
1085
|
+
ref: z9.string().min(1),
|
|
1086
|
+
message: z9.string().min(1)
|
|
1144
1087
|
}).strict();
|
|
1145
|
-
var readSetEntrySchema =
|
|
1146
|
-
store_uuid:
|
|
1147
|
-
alias:
|
|
1148
|
-
remote:
|
|
1088
|
+
var readSetEntrySchema = z9.object({
|
|
1089
|
+
store_uuid: z9.string().min(1),
|
|
1090
|
+
alias: z9.string().min(1),
|
|
1091
|
+
remote: z9.string().min(1).optional(),
|
|
1149
1092
|
// Whether this store accepts writes from the current context. Personal
|
|
1150
1093
|
// store is writable; shared stores writable iff mounted with write intent.
|
|
1151
|
-
writable:
|
|
1094
|
+
writable: z9.boolean()
|
|
1152
1095
|
}).strict();
|
|
1153
|
-
var storeReadSetSchema =
|
|
1154
|
-
stores:
|
|
1155
|
-
warnings:
|
|
1096
|
+
var storeReadSetSchema = z9.object({
|
|
1097
|
+
stores: z9.array(readSetEntrySchema),
|
|
1098
|
+
warnings: z9.array(storeResolverWarningSchema)
|
|
1156
1099
|
}).strict();
|
|
1157
|
-
var writeTargetSchema =
|
|
1158
|
-
store_uuid:
|
|
1159
|
-
alias:
|
|
1100
|
+
var writeTargetSchema = z9.object({
|
|
1101
|
+
store_uuid: z9.string().min(1),
|
|
1102
|
+
alias: z9.string().min(1)
|
|
1160
1103
|
}).strict();
|
|
1161
|
-
var storeResolveInputSchema =
|
|
1104
|
+
var storeResolveInputSchema = z9.object({
|
|
1162
1105
|
// Machine identity (S33) — namespaces personal ids; identifies personal store.
|
|
1163
|
-
uid:
|
|
1106
|
+
uid: z9.string().min(1),
|
|
1164
1107
|
// Stores mounted on this machine (from global config).
|
|
1165
|
-
mountedStores:
|
|
1166
|
-
|
|
1167
|
-
store_uuid:
|
|
1168
|
-
alias:
|
|
1169
|
-
|
|
1170
|
-
|
|
1108
|
+
mountedStores: z9.array(
|
|
1109
|
+
z9.object({
|
|
1110
|
+
store_uuid: z9.string().min(1),
|
|
1111
|
+
alias: z9.string().min(1),
|
|
1112
|
+
mount_name: z9.string().min(1).optional(),
|
|
1113
|
+
remote: z9.string().min(1).optional(),
|
|
1114
|
+
writable: z9.boolean().default(true),
|
|
1171
1115
|
// Marks the implicit personal store.
|
|
1172
|
-
personal:
|
|
1116
|
+
personal: z9.boolean().default(false)
|
|
1173
1117
|
}).strict()
|
|
1174
1118
|
),
|
|
1175
1119
|
// The project's declared required_stores (ids/aliases + optional remote).
|
|
1176
|
-
requiredStores:
|
|
1177
|
-
|
|
1178
|
-
id:
|
|
1179
|
-
suggested_remote:
|
|
1120
|
+
requiredStores: z9.array(
|
|
1121
|
+
z9.object({
|
|
1122
|
+
id: z9.string().min(1),
|
|
1123
|
+
suggested_remote: z9.string().min(1).optional()
|
|
1180
1124
|
}).strict()
|
|
1181
1125
|
),
|
|
1182
1126
|
// Alias selected as the active write store for non-personal scopes, if any.
|
|
1183
|
-
activeWriteAlias:
|
|
1127
|
+
activeWriteAlias: z9.string().min(1).optional(),
|
|
1128
|
+
// Scope-aware write routes. Exact scope wins first, then longest prefix route.
|
|
1129
|
+
writeRoutes: z9.array(
|
|
1130
|
+
z9.object({
|
|
1131
|
+
scope: z9.string().min(1),
|
|
1132
|
+
store: z9.string().min(1)
|
|
1133
|
+
}).strict()
|
|
1134
|
+
).optional().default([]),
|
|
1135
|
+
defaultWriteAlias: z9.string().min(1).optional()
|
|
1184
1136
|
}).strict();
|
|
1185
|
-
var projectRootGoldenCaseSchema =
|
|
1186
|
-
name:
|
|
1187
|
-
note:
|
|
1137
|
+
var projectRootGoldenCaseSchema = z9.object({
|
|
1138
|
+
name: z9.string().min(1),
|
|
1139
|
+
note: z9.string().optional(),
|
|
1188
1140
|
signals: projectRootSignalsSchema,
|
|
1189
1141
|
// null expected = resolver should return no root for these signals.
|
|
1190
1142
|
expected: projectRootResolutionSchema.nullable()
|
|
1191
1143
|
}).strict();
|
|
1192
|
-
var projectRootGoldenFileSchema =
|
|
1193
|
-
contract:
|
|
1194
|
-
cases:
|
|
1144
|
+
var projectRootGoldenFileSchema = z9.object({
|
|
1145
|
+
contract: z9.literal("project-root.golden"),
|
|
1146
|
+
cases: z9.array(projectRootGoldenCaseSchema).min(1)
|
|
1195
1147
|
}).strict();
|
|
1196
|
-
var readSetGoldenCaseSchema =
|
|
1197
|
-
name:
|
|
1198
|
-
note:
|
|
1148
|
+
var readSetGoldenCaseSchema = z9.object({
|
|
1149
|
+
name: z9.string().min(1),
|
|
1150
|
+
note: z9.string().optional(),
|
|
1199
1151
|
input: storeResolveInputSchema,
|
|
1200
1152
|
// Scope under test for the write-target expectation.
|
|
1201
|
-
writeScope:
|
|
1202
|
-
expected:
|
|
1153
|
+
writeScope: z9.string().min(1),
|
|
1154
|
+
expected: z9.object({
|
|
1203
1155
|
readSet: storeReadSetSchema,
|
|
1204
1156
|
writeTarget: writeTargetSchema.nullable(),
|
|
1205
|
-
writeWarnings:
|
|
1157
|
+
writeWarnings: z9.array(storeResolverWarningSchema)
|
|
1206
1158
|
}).strict()
|
|
1207
1159
|
}).strict();
|
|
1208
|
-
var readSetGoldenFileSchema =
|
|
1209
|
-
contract:
|
|
1210
|
-
cases:
|
|
1160
|
+
var readSetGoldenFileSchema = z9.object({
|
|
1161
|
+
contract: z9.literal("read-set.golden"),
|
|
1162
|
+
cases: z9.array(readSetGoldenCaseSchema).min(1)
|
|
1211
1163
|
}).strict();
|
|
1212
1164
|
|
|
1213
1165
|
// 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
1166
|
function createProjectRootResolver() {
|
|
1221
1167
|
return {
|
|
1222
1168
|
resolve(signals) {
|
|
@@ -1254,12 +1200,65 @@ function personalEntry(input) {
|
|
|
1254
1200
|
}
|
|
1255
1201
|
return entry;
|
|
1256
1202
|
}
|
|
1203
|
+
function readSetEntryFromMounted(store) {
|
|
1204
|
+
const entry = {
|
|
1205
|
+
store_uuid: store.store_uuid,
|
|
1206
|
+
alias: store.alias,
|
|
1207
|
+
writable: store.writable
|
|
1208
|
+
};
|
|
1209
|
+
if (store.remote !== void 0) {
|
|
1210
|
+
entry.remote = store.remote;
|
|
1211
|
+
return { entry };
|
|
1212
|
+
}
|
|
1213
|
+
return {
|
|
1214
|
+
entry,
|
|
1215
|
+
warning: {
|
|
1216
|
+
code: "local_only_no_remote",
|
|
1217
|
+
ref: store.alias,
|
|
1218
|
+
message: `store '${store.alias}' is local-only; add a git remote to back it up (\`fabric store ... \` / doctor nudge)`
|
|
1219
|
+
}
|
|
1220
|
+
};
|
|
1221
|
+
}
|
|
1222
|
+
function isMountedPersonal(input, storeUuid) {
|
|
1223
|
+
return input.mountedStores.some((store) => store.store_uuid === storeUuid && store.personal);
|
|
1224
|
+
}
|
|
1225
|
+
function routeMatches(routeScope, scope) {
|
|
1226
|
+
return scope === routeScope || scope.startsWith(`${routeScope}:`);
|
|
1227
|
+
}
|
|
1228
|
+
function resolveRouteAlias(input, scope) {
|
|
1229
|
+
const routes = input.writeRoutes ?? [];
|
|
1230
|
+
const exact = routes.find((route) => route.scope === scope);
|
|
1231
|
+
if (exact !== void 0) {
|
|
1232
|
+
return exact.store;
|
|
1233
|
+
}
|
|
1234
|
+
const prefix = routes.filter((route) => routeMatches(route.scope, scope)).sort((a, b) => b.scope.length - a.scope.length)[0];
|
|
1235
|
+
return prefix?.store ?? input.defaultWriteAlias ?? input.activeWriteAlias;
|
|
1236
|
+
}
|
|
1237
|
+
function hasMultipleSharedStores(input, readSet) {
|
|
1238
|
+
return readSet.stores.filter((store) => !isMountedPersonal(input, store.store_uuid)).length > 1;
|
|
1239
|
+
}
|
|
1240
|
+
function hasExplicitRouteOrDefault(input, scope) {
|
|
1241
|
+
const routes = input.writeRoutes ?? [];
|
|
1242
|
+
return routes.some((route) => routeMatches(route.scope, scope)) || input.defaultWriteAlias !== void 0;
|
|
1243
|
+
}
|
|
1257
1244
|
function createStoreResolver() {
|
|
1258
1245
|
return {
|
|
1259
1246
|
resolveReadSet(input) {
|
|
1260
1247
|
const stores = [];
|
|
1261
1248
|
const warnings = [];
|
|
1249
|
+
const seenStoreUuids = /* @__PURE__ */ new Set();
|
|
1262
1250
|
for (const req of input.requiredStores) {
|
|
1251
|
+
if (req.suggested_remote === "$personal") {
|
|
1252
|
+
const personal2 = findPersonal(input);
|
|
1253
|
+
if (personal2 === void 0) {
|
|
1254
|
+
warnings.push({
|
|
1255
|
+
code: "missing_store",
|
|
1256
|
+
ref: req.id,
|
|
1257
|
+
message: `required store '${req.id}' is not mounted; run \`fabric store add\` (suggested remote: $personal)`
|
|
1258
|
+
});
|
|
1259
|
+
}
|
|
1260
|
+
continue;
|
|
1261
|
+
}
|
|
1263
1262
|
const matched = input.mountedStores.find(
|
|
1264
1263
|
(m) => !m.personal && (m.alias === req.id || m.store_uuid === req.id)
|
|
1265
1264
|
);
|
|
@@ -1272,25 +1271,20 @@ function createStoreResolver() {
|
|
|
1272
1271
|
});
|
|
1273
1272
|
continue;
|
|
1274
1273
|
}
|
|
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
|
-
});
|
|
1274
|
+
if (seenStoreUuids.has(matched.store_uuid)) {
|
|
1275
|
+
continue;
|
|
1276
|
+
}
|
|
1277
|
+
const { entry, warning } = readSetEntryFromMounted(matched);
|
|
1278
|
+
if (warning !== void 0) {
|
|
1279
|
+
warnings.push(warning);
|
|
1288
1280
|
}
|
|
1289
1281
|
stores.push(entry);
|
|
1282
|
+
seenStoreUuids.add(matched.store_uuid);
|
|
1290
1283
|
}
|
|
1291
1284
|
const personal = personalEntry(input);
|
|
1292
|
-
if (personal !== void 0) {
|
|
1285
|
+
if (personal !== void 0 && !seenStoreUuids.has(personal.store_uuid)) {
|
|
1293
1286
|
stores.push(personal);
|
|
1287
|
+
seenStoreUuids.add(personal.store_uuid);
|
|
1294
1288
|
}
|
|
1295
1289
|
return { stores, warnings };
|
|
1296
1290
|
},
|
|
@@ -1311,15 +1305,31 @@ function createStoreResolver() {
|
|
|
1311
1305
|
}
|
|
1312
1306
|
return { target: { store_uuid: p.store_uuid, alias: p.alias }, warnings: [] };
|
|
1313
1307
|
}
|
|
1314
|
-
const
|
|
1308
|
+
const readSet = this.resolveReadSet(input);
|
|
1309
|
+
if (hasMultipleSharedStores(input, readSet) && !hasExplicitRouteOrDefault(input, scope)) {
|
|
1310
|
+
return {
|
|
1311
|
+
target: null,
|
|
1312
|
+
warnings: [
|
|
1313
|
+
{
|
|
1314
|
+
code: "missing_write_route",
|
|
1315
|
+
ref: scope,
|
|
1316
|
+
message: `scope '${scope}' has no explicit write route; set \`fabric store route-write ${scope} <alias>\``
|
|
1317
|
+
}
|
|
1318
|
+
]
|
|
1319
|
+
};
|
|
1320
|
+
}
|
|
1321
|
+
const routeAlias = resolveRouteAlias(input, scope);
|
|
1322
|
+
const active = routeAlias === void 0 ? void 0 : readSet.stores.find(
|
|
1323
|
+
(store) => store.writable && !isMountedPersonal(input, store.store_uuid) && (store.alias === routeAlias || store.store_uuid === routeAlias)
|
|
1324
|
+
);
|
|
1315
1325
|
if (active === void 0) {
|
|
1316
1326
|
return {
|
|
1317
1327
|
target: null,
|
|
1318
1328
|
warnings: [
|
|
1319
1329
|
{
|
|
1320
1330
|
code: "alias_unresolved",
|
|
1321
|
-
ref:
|
|
1322
|
-
message: `no writable store for scope '${scope}'; set
|
|
1331
|
+
ref: routeAlias ?? scope,
|
|
1332
|
+
message: `no writable store for scope '${scope}'; set a write route or default write store`
|
|
1323
1333
|
}
|
|
1324
1334
|
]
|
|
1325
1335
|
};
|
|
@@ -1333,7 +1343,8 @@ function createStoreResolver() {
|
|
|
1333
1343
|
}
|
|
1334
1344
|
|
|
1335
1345
|
// src/resolver/store-disk-reader.ts
|
|
1336
|
-
import { existsSync, readdirSync, readFileSync
|
|
1346
|
+
import { existsSync, lstatSync, readdirSync, readFileSync } from "fs";
|
|
1347
|
+
import { readFile } from "fs/promises";
|
|
1337
1348
|
import { join } from "path";
|
|
1338
1349
|
function readStoreIdentity(absDir) {
|
|
1339
1350
|
const identityFile = join(absDir, STORE_LAYOUT.identityFile);
|
|
@@ -1349,6 +1360,17 @@ function readStoreIdentity(absDir) {
|
|
|
1349
1360
|
const parsed = storeIdentitySchema.safeParse(raw);
|
|
1350
1361
|
return parsed.success ? parsed.data : null;
|
|
1351
1362
|
}
|
|
1363
|
+
async function readStoreIdentityAsync(absDir) {
|
|
1364
|
+
const identityFile = join(absDir, STORE_LAYOUT.identityFile);
|
|
1365
|
+
let raw;
|
|
1366
|
+
try {
|
|
1367
|
+
raw = JSON.parse(await readFile(identityFile, "utf8"));
|
|
1368
|
+
} catch {
|
|
1369
|
+
return null;
|
|
1370
|
+
}
|
|
1371
|
+
const parsed = storeIdentitySchema.safeParse(raw);
|
|
1372
|
+
return parsed.success ? parsed.data : null;
|
|
1373
|
+
}
|
|
1352
1374
|
function recognizeStoreDir(absDir) {
|
|
1353
1375
|
return readStoreIdentity(absDir) !== null;
|
|
1354
1376
|
}
|
|
@@ -1408,10 +1430,14 @@ function findStoreExecutableViolations(absDir, options = {}) {
|
|
|
1408
1430
|
const relPath = rel === "" ? entry : `${rel}/${entry}`;
|
|
1409
1431
|
let stat;
|
|
1410
1432
|
try {
|
|
1411
|
-
stat =
|
|
1433
|
+
stat = lstatSync(abs);
|
|
1412
1434
|
} catch {
|
|
1413
1435
|
continue;
|
|
1414
1436
|
}
|
|
1437
|
+
if (stat.isSymbolicLink()) {
|
|
1438
|
+
violations.push(relPath);
|
|
1439
|
+
continue;
|
|
1440
|
+
}
|
|
1415
1441
|
if (stat.isDirectory()) {
|
|
1416
1442
|
walk(abs, relPath, depth + 1);
|
|
1417
1443
|
continue;
|
|
@@ -1525,9 +1551,10 @@ function resolveCandidates(candidates, options = {}) {
|
|
|
1525
1551
|
}
|
|
1526
1552
|
|
|
1527
1553
|
// src/store/core.ts
|
|
1528
|
-
import {
|
|
1529
|
-
import {
|
|
1554
|
+
import { execFile } from "child_process";
|
|
1555
|
+
import { access, mkdir, readdir, readFile as readFile2, writeFile } from "fs/promises";
|
|
1530
1556
|
import { join as join2 } from "path";
|
|
1557
|
+
import { promisify } from "util";
|
|
1531
1558
|
var STORE_PENDING_DIR = "pending";
|
|
1532
1559
|
var STORE_GITIGNORE = [
|
|
1533
1560
|
"# v2.1 store \u2014 volatile / derived data is never committed",
|
|
@@ -1536,96 +1563,106 @@ var STORE_GITIGNORE = [
|
|
|
1536
1563
|
".cache/",
|
|
1537
1564
|
""
|
|
1538
1565
|
].join("\n");
|
|
1539
|
-
|
|
1540
|
-
|
|
1566
|
+
var execFileAsync = promisify(execFile);
|
|
1567
|
+
async function git(cwd, args) {
|
|
1568
|
+
await execFileAsync("git", args, { cwd });
|
|
1541
1569
|
}
|
|
1542
|
-
function initStore(absDir, identity, options = {}) {
|
|
1570
|
+
async function initStore(absDir, identity, options = {}) {
|
|
1543
1571
|
const parsed = storeIdentitySchema.parse(identity);
|
|
1544
1572
|
const identityFile = join2(absDir, STORE_LAYOUT.identityFile);
|
|
1545
|
-
|
|
1573
|
+
try {
|
|
1574
|
+
await access(identityFile);
|
|
1546
1575
|
throw new Error(`store already initialized at ${absDir} (store.json exists)`);
|
|
1576
|
+
} catch (err) {
|
|
1577
|
+
if (err instanceof Error && err.message.includes("already initialized")) {
|
|
1578
|
+
throw err;
|
|
1579
|
+
}
|
|
1547
1580
|
}
|
|
1548
1581
|
for (const type of STORE_KNOWLEDGE_TYPE_DIRS) {
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1582
|
+
const typeDir = join2(absDir, STORE_LAYOUT.knowledgeDir, type);
|
|
1583
|
+
await mkdir(typeDir, { recursive: true });
|
|
1584
|
+
await writeFile(join2(typeDir, ".gitkeep"), "", "utf8");
|
|
1585
|
+
}
|
|
1586
|
+
await mkdir(join2(absDir, STORE_LAYOUT.knowledgeDir, STORE_PENDING_DIR), { recursive: true });
|
|
1587
|
+
await mkdir(join2(absDir, STORE_LAYOUT.bindingsDir), { recursive: true });
|
|
1588
|
+
await mkdir(join2(absDir, STORE_LAYOUT.stateDir), { recursive: true });
|
|
1589
|
+
await writeFile(identityFile, `${JSON.stringify(parsed, null, 2)}
|
|
1555
1590
|
`, "utf8");
|
|
1556
|
-
|
|
1591
|
+
await writeFile(join2(absDir, ".gitignore"), STORE_GITIGNORE, "utf8");
|
|
1557
1592
|
if (options.git !== false) {
|
|
1558
|
-
git(absDir, ["init", "-b", "main"]);
|
|
1593
|
+
await git(absDir, ["init", "-b", "main"]);
|
|
1559
1594
|
}
|
|
1560
|
-
const readBack =
|
|
1595
|
+
const readBack = await readStoreIdentityAsync(absDir);
|
|
1561
1596
|
if (readBack === null) {
|
|
1562
1597
|
throw new Error(`store init wrote an unrecognizable store.json at ${absDir}`);
|
|
1563
1598
|
}
|
|
1564
1599
|
return readBack;
|
|
1565
1600
|
}
|
|
1566
|
-
function listMarkdown(dir) {
|
|
1567
|
-
|
|
1601
|
+
async function listMarkdown(dir) {
|
|
1602
|
+
let entries;
|
|
1603
|
+
try {
|
|
1604
|
+
entries = await readdir(dir);
|
|
1605
|
+
} catch {
|
|
1568
1606
|
return [];
|
|
1569
1607
|
}
|
|
1570
|
-
return
|
|
1608
|
+
return entries.filter((name) => name.endsWith(".md")).sort().map((name) => join2(dir, name));
|
|
1571
1609
|
}
|
|
1572
|
-
function listStoreKnowledge(store) {
|
|
1610
|
+
async function listStoreKnowledge(store) {
|
|
1573
1611
|
const refs = [];
|
|
1574
1612
|
for (const type of STORE_KNOWLEDGE_TYPE_DIRS) {
|
|
1575
|
-
for (const file of listMarkdown(join2(store.dir, STORE_LAYOUT.knowledgeDir, type))) {
|
|
1613
|
+
for (const file of await listMarkdown(join2(store.dir, STORE_LAYOUT.knowledgeDir, type))) {
|
|
1576
1614
|
refs.push({ store_uuid: store.store_uuid, alias: store.alias, type, file });
|
|
1577
1615
|
}
|
|
1578
1616
|
}
|
|
1579
1617
|
return refs;
|
|
1580
1618
|
}
|
|
1581
|
-
function readKnowledgeAcrossStores(stores) {
|
|
1582
|
-
|
|
1619
|
+
async function readKnowledgeAcrossStores(stores) {
|
|
1620
|
+
const lists = await Promise.all(stores.map((store) => listStoreKnowledge(store)));
|
|
1621
|
+
return lists.flat();
|
|
1583
1622
|
}
|
|
1584
1623
|
function storeProjectsPath(storeDir) {
|
|
1585
1624
|
return join2(storeDir, STORE_LAYOUT.projectsFile);
|
|
1586
1625
|
}
|
|
1587
|
-
function readStoreProjects(storeDir) {
|
|
1626
|
+
async function readStoreProjects(storeDir) {
|
|
1588
1627
|
const path = storeProjectsPath(storeDir);
|
|
1589
|
-
if (!existsSync2(path)) {
|
|
1590
|
-
return [];
|
|
1591
|
-
}
|
|
1592
1628
|
let raw;
|
|
1593
1629
|
try {
|
|
1594
|
-
raw = JSON.parse(
|
|
1630
|
+
raw = JSON.parse(await readFile2(path, "utf8"));
|
|
1595
1631
|
} catch {
|
|
1596
1632
|
return [];
|
|
1597
1633
|
}
|
|
1598
1634
|
const parsed = storeProjectsFileSchema.safeParse(raw);
|
|
1599
1635
|
return parsed.success ? parsed.data.projects : [];
|
|
1600
1636
|
}
|
|
1601
|
-
function storeHasProject(storeDir, id) {
|
|
1602
|
-
return readStoreProjects(storeDir).some((p) => p.id === id);
|
|
1637
|
+
async function storeHasProject(storeDir, id) {
|
|
1638
|
+
return (await readStoreProjects(storeDir)).some((p) => p.id === id);
|
|
1603
1639
|
}
|
|
1604
|
-
function addStoreProject(storeDir, project) {
|
|
1640
|
+
async function addStoreProject(storeDir, project) {
|
|
1605
1641
|
const parsed = storeProjectSchema.parse(project);
|
|
1606
|
-
const existing = readStoreProjects(storeDir);
|
|
1642
|
+
const existing = await readStoreProjects(storeDir);
|
|
1607
1643
|
if (existing.some((p) => p.id === parsed.id)) {
|
|
1608
1644
|
throw new Error(`project '${parsed.id}' already exists in store at ${storeDir}`);
|
|
1609
1645
|
}
|
|
1610
1646
|
const next = [...existing, parsed];
|
|
1611
1647
|
const validated = storeProjectsFileSchema.parse({ projects: next });
|
|
1612
|
-
|
|
1648
|
+
await writeFile(storeProjectsPath(storeDir), `${JSON.stringify(validated, null, 2)}
|
|
1613
1649
|
`, "utf8");
|
|
1614
1650
|
return validated.projects;
|
|
1615
1651
|
}
|
|
1616
|
-
function aggregatePendingAcrossStores(stores) {
|
|
1617
|
-
|
|
1618
|
-
(store) => listMarkdown(join2(store.dir, STORE_LAYOUT.knowledgeDir, STORE_PENDING_DIR)).map((file) => ({
|
|
1652
|
+
async function aggregatePendingAcrossStores(stores) {
|
|
1653
|
+
const lists = await Promise.all(stores.map(
|
|
1654
|
+
async (store) => (await listMarkdown(join2(store.dir, STORE_LAYOUT.knowledgeDir, STORE_PENDING_DIR))).map((file) => ({
|
|
1619
1655
|
store_uuid: store.store_uuid,
|
|
1620
1656
|
alias: store.alias,
|
|
1621
1657
|
type: STORE_PENDING_DIR,
|
|
1622
1658
|
file
|
|
1623
1659
|
}))
|
|
1624
|
-
);
|
|
1660
|
+
));
|
|
1661
|
+
return lists.flat();
|
|
1625
1662
|
}
|
|
1626
1663
|
|
|
1627
1664
|
// src/store/store-counters.ts
|
|
1628
|
-
import { existsSync as
|
|
1665
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, readdirSync as readdirSync2, writeFileSync } from "fs";
|
|
1629
1666
|
import { join as join3 } from "path";
|
|
1630
1667
|
function storeCountersPath(storeDir) {
|
|
1631
1668
|
return join3(storeDir, STORE_LAYOUT.countersFile);
|
|
@@ -1633,7 +1670,7 @@ function storeCountersPath(storeDir) {
|
|
|
1633
1670
|
function readStoreCounters(storeDir) {
|
|
1634
1671
|
let raw;
|
|
1635
1672
|
try {
|
|
1636
|
-
raw =
|
|
1673
|
+
raw = readFileSync2(storeCountersPath(storeDir), "utf8");
|
|
1637
1674
|
} catch {
|
|
1638
1675
|
return defaultAgentsMetaCounters();
|
|
1639
1676
|
}
|
|
@@ -1646,10 +1683,39 @@ function readStoreCounters(storeDir) {
|
|
|
1646
1683
|
const result = AgentsMetaCountersSchema.safeParse(parsed);
|
|
1647
1684
|
return result.success ? result.data : defaultAgentsMetaCounters();
|
|
1648
1685
|
}
|
|
1686
|
+
function preserveCorruptCounters(path, raw) {
|
|
1687
|
+
const corruptedPath = `${path}.corrupted.${Date.now()}`;
|
|
1688
|
+
writeFileSync(corruptedPath, raw, "utf8");
|
|
1689
|
+
return corruptedPath;
|
|
1690
|
+
}
|
|
1691
|
+
function readStoreCountersForAllocation(storeDir) {
|
|
1692
|
+
const path = storeCountersPath(storeDir);
|
|
1693
|
+
if (!existsSync2(path)) {
|
|
1694
|
+
return defaultAgentsMetaCounters();
|
|
1695
|
+
}
|
|
1696
|
+
const raw = readFileSync2(path, "utf8");
|
|
1697
|
+
let parsed;
|
|
1698
|
+
try {
|
|
1699
|
+
parsed = JSON.parse(raw);
|
|
1700
|
+
} catch (error) {
|
|
1701
|
+
const corruptedPath = preserveCorruptCounters(path, raw);
|
|
1702
|
+
throw new Error(
|
|
1703
|
+
`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)}`
|
|
1704
|
+
);
|
|
1705
|
+
}
|
|
1706
|
+
const result = AgentsMetaCountersSchema.safeParse(parsed);
|
|
1707
|
+
if (!result.success) {
|
|
1708
|
+
const corruptedPath = preserveCorruptCounters(path, raw);
|
|
1709
|
+
throw new Error(
|
|
1710
|
+
`store counters.json is schema-invalid; forensic copy saved to ${corruptedPath}. Run doctor --fix or reconcileStoreCounters before allocating a new stable_id.`
|
|
1711
|
+
);
|
|
1712
|
+
}
|
|
1713
|
+
return result.data;
|
|
1714
|
+
}
|
|
1649
1715
|
async function allocateStoreKnowledgeId(layer, type, storeDir) {
|
|
1650
1716
|
const countersPath = storeCountersPath(storeDir);
|
|
1651
1717
|
return withFileLock(`${countersPath}.lock`, async () => {
|
|
1652
|
-
const counters =
|
|
1718
|
+
const counters = readStoreCountersForAllocation(storeDir);
|
|
1653
1719
|
const { id, nextCounters } = allocateKnowledgeId(layer, type, counters);
|
|
1654
1720
|
await atomicWriteJson(countersPath, nextCounters, { indent: 2 });
|
|
1655
1721
|
return id;
|
|
@@ -1658,7 +1724,7 @@ async function allocateStoreKnowledgeId(layer, type, storeDir) {
|
|
|
1658
1724
|
function readEntryId(file) {
|
|
1659
1725
|
let content;
|
|
1660
1726
|
try {
|
|
1661
|
-
content =
|
|
1727
|
+
content = readFileSync2(file, "utf8");
|
|
1662
1728
|
} catch {
|
|
1663
1729
|
return null;
|
|
1664
1730
|
}
|
|
@@ -1678,10 +1744,10 @@ function reconcileStoreCounters(storeDir) {
|
|
|
1678
1744
|
};
|
|
1679
1745
|
for (const type of STORE_KNOWLEDGE_TYPE_DIRS) {
|
|
1680
1746
|
const dir = join3(storeDir, STORE_LAYOUT.knowledgeDir, type);
|
|
1681
|
-
if (!
|
|
1747
|
+
if (!existsSync2(dir)) {
|
|
1682
1748
|
continue;
|
|
1683
1749
|
}
|
|
1684
|
-
for (const name of
|
|
1750
|
+
for (const name of readdirSync2(dir)) {
|
|
1685
1751
|
if (!name.endsWith(".md")) {
|
|
1686
1752
|
continue;
|
|
1687
1753
|
}
|
|
@@ -1694,52 +1760,28 @@ function reconcileStoreCounters(storeDir) {
|
|
|
1694
1760
|
next[layerKey][typeCode] = Math.max(next[layerKey][typeCode], parsed.counter);
|
|
1695
1761
|
}
|
|
1696
1762
|
}
|
|
1697
|
-
|
|
1763
|
+
writeFileSync(storeCountersPath(storeDir), `${JSON.stringify(next, null, 2)}
|
|
1698
1764
|
`, "utf8");
|
|
1699
1765
|
return next;
|
|
1700
1766
|
}
|
|
1701
1767
|
|
|
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
1768
|
// src/store/project-config-io.ts
|
|
1727
|
-
import { existsSync as
|
|
1728
|
-
import { join as
|
|
1769
|
+
import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
1770
|
+
import { join as join4 } from "path";
|
|
1729
1771
|
function projectConfigPath(projectRoot) {
|
|
1730
|
-
return
|
|
1772
|
+
return join4(projectRoot, ".fabric", "fabric-config.json");
|
|
1731
1773
|
}
|
|
1732
1774
|
function loadProjectConfig(projectRoot) {
|
|
1733
1775
|
const path = projectConfigPath(projectRoot);
|
|
1734
|
-
if (!
|
|
1776
|
+
if (!existsSync3(path)) {
|
|
1735
1777
|
return null;
|
|
1736
1778
|
}
|
|
1737
|
-
return fabricConfigSchema.parse(JSON.parse(
|
|
1779
|
+
return fabricConfigSchema.parse(JSON.parse(readFileSync3(path, "utf8")));
|
|
1738
1780
|
}
|
|
1739
1781
|
function saveProjectConfig(config, projectRoot) {
|
|
1740
1782
|
const validated = fabricConfigSchema.parse(config);
|
|
1741
|
-
|
|
1742
|
-
|
|
1783
|
+
mkdirSync(join4(projectRoot, ".fabric"), { recursive: true });
|
|
1784
|
+
writeFileSync2(projectConfigPath(projectRoot), `${JSON.stringify(validated, null, 2)}
|
|
1743
1785
|
`, "utf8");
|
|
1744
1786
|
}
|
|
1745
1787
|
|
|
@@ -1755,6 +1797,7 @@ function buildStoreResolveInput(projectRoot, globalRoot = resolveGlobalRoot()) {
|
|
|
1755
1797
|
mountedStores: global.stores.map((s) => ({
|
|
1756
1798
|
store_uuid: s.store_uuid,
|
|
1757
1799
|
alias: s.alias,
|
|
1800
|
+
...s.mount_name === void 0 ? {} : { mount_name: s.mount_name },
|
|
1758
1801
|
...s.remote === void 0 ? {} : { remote: s.remote },
|
|
1759
1802
|
writable: s.writable ?? true,
|
|
1760
1803
|
personal: s.personal ?? false
|
|
@@ -1765,22 +1808,43 @@ function buildStoreResolveInput(projectRoot, globalRoot = resolveGlobalRoot()) {
|
|
|
1765
1808
|
...r.suggested_remote === void 0 ? {} : { suggested_remote: r.suggested_remote }
|
|
1766
1809
|
})
|
|
1767
1810
|
),
|
|
1768
|
-
...project?.active_write_store === void 0 ? {} : { activeWriteAlias: project.active_write_store }
|
|
1811
|
+
...project?.active_write_store === void 0 ? {} : { activeWriteAlias: project.active_write_store },
|
|
1812
|
+
writeRoutes: project?.write_routes ?? [],
|
|
1813
|
+
...project?.default_write_store === void 0 ? {} : { defaultWriteAlias: project.default_write_store }
|
|
1769
1814
|
};
|
|
1770
1815
|
}
|
|
1771
1816
|
|
|
1772
1817
|
// 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
|
|
1818
|
+
var CREDENTIAL_RULES = [
|
|
1819
|
+
{ rule: "aws-access-key-id", re: /\bAKIA[0-9A-Z]{16}\b/, category: "credential" },
|
|
1820
|
+
{ rule: "private-key-block", re: /-----BEGIN (?:RSA |EC |OPENSSH |DSA |PGP )?PRIVATE KEY-----/, category: "credential" },
|
|
1821
|
+
{ rule: "openai-api-key", re: /\bsk-[A-Za-z0-9]{20,}\b/, category: "credential" },
|
|
1822
|
+
{ rule: "github-token", re: /\bgh[pousr]_[A-Za-z0-9]{20,}\b/, category: "credential" },
|
|
1823
|
+
{ rule: "slack-token", re: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/, category: "credential" },
|
|
1779
1824
|
{
|
|
1780
1825
|
rule: "credential-assignment",
|
|
1781
|
-
re: /(?:password|passwd|secret|api[_-]?key|access[_-]?token|token)\s*[:=]\s*['"][^'"\s]{8,}[
|
|
1826
|
+
re: /(?:password|passwd|secret|api[_-]?key|access[_-]?token|token)\s*[:=]\s*(?:"[^'"\s]{8,}"|'[^'"\s]{8,}'|[A-Za-z0-9_./+=:@-]{8,})/i,
|
|
1827
|
+
category: "credential"
|
|
1782
1828
|
}
|
|
1783
1829
|
];
|
|
1830
|
+
var PII_RULES = [
|
|
1831
|
+
{
|
|
1832
|
+
rule: "email-address",
|
|
1833
|
+
re: /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/i,
|
|
1834
|
+
category: "pii"
|
|
1835
|
+
},
|
|
1836
|
+
{
|
|
1837
|
+
rule: "ipv4-address",
|
|
1838
|
+
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/,
|
|
1839
|
+
category: "pii"
|
|
1840
|
+
},
|
|
1841
|
+
{
|
|
1842
|
+
rule: "phone-number",
|
|
1843
|
+
re: /(?<!\d)(?:\+?1[-.\s]?)?(?:\(?\d{3}\)?[-.\s]?)\d{3}[-.\s]?\d{4}(?!\d)/,
|
|
1844
|
+
category: "pii"
|
|
1845
|
+
}
|
|
1846
|
+
];
|
|
1847
|
+
var SECRET_RULES = [...CREDENTIAL_RULES, ...PII_RULES];
|
|
1784
1848
|
function scanForSecrets(content) {
|
|
1785
1849
|
const findings = [];
|
|
1786
1850
|
const lines = content.split(/\r?\n/u);
|
|
@@ -1794,12 +1858,26 @@ function scanForSecrets(content) {
|
|
|
1794
1858
|
return findings;
|
|
1795
1859
|
}
|
|
1796
1860
|
function hasSecrets(content) {
|
|
1797
|
-
|
|
1861
|
+
const lines = content.split(/\r?\n/u);
|
|
1862
|
+
for (const line of lines) {
|
|
1863
|
+
for (const { re } of CREDENTIAL_RULES) {
|
|
1864
|
+
if (re.test(line)) {
|
|
1865
|
+
return true;
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
return false;
|
|
1798
1870
|
}
|
|
1799
1871
|
var REDACTION_PLACEHOLDER_PREFIX = "[REDACTED:";
|
|
1800
1872
|
function redactSecrets(content) {
|
|
1873
|
+
return redactByRules(content, SECRET_RULES);
|
|
1874
|
+
}
|
|
1875
|
+
function redactPii(content) {
|
|
1876
|
+
return redactByRules(content, PII_RULES);
|
|
1877
|
+
}
|
|
1878
|
+
function redactByRules(content, rules) {
|
|
1801
1879
|
let out = content;
|
|
1802
|
-
for (const { rule, re } of
|
|
1880
|
+
for (const { rule, re } of rules) {
|
|
1803
1881
|
const flags = re.flags.includes("i") ? "gi" : "g";
|
|
1804
1882
|
out = out.replace(new RegExp(re.source, flags), `${REDACTION_PLACEHOLDER_PREFIX}${rule}]`);
|
|
1805
1883
|
}
|
|
@@ -1922,10 +2000,10 @@ function buildDebugBundle(input) {
|
|
|
1922
2000
|
}
|
|
1923
2001
|
|
|
1924
2002
|
// src/schemas/provenance.ts
|
|
1925
|
-
import { z as
|
|
1926
|
-
var knowledgeProvenanceSchema =
|
|
2003
|
+
import { z as z10 } from "zod";
|
|
2004
|
+
var knowledgeProvenanceSchema = z10.object({
|
|
1927
2005
|
store_uuid: storeUuidSchema,
|
|
1928
|
-
alias:
|
|
2006
|
+
alias: z10.string().min(1),
|
|
1929
2007
|
local_id: localKnowledgeIdSchema,
|
|
1930
2008
|
global_ref: globalRefSchema,
|
|
1931
2009
|
// Optional scope coordinate of the entry (resolution axis); present when the
|
|
@@ -1934,7 +2012,7 @@ var knowledgeProvenanceSchema = z12.object({
|
|
|
1934
2012
|
}).strict();
|
|
1935
2013
|
|
|
1936
2014
|
// src/schemas/mcp-store-contracts.ts
|
|
1937
|
-
import { z as
|
|
2015
|
+
import { z as z11 } from "zod";
|
|
1938
2016
|
var MCP_STORE_AWARE_TOOLS = [
|
|
1939
2017
|
"fab_recall",
|
|
1940
2018
|
"fab_plan_context",
|
|
@@ -1943,14 +2021,14 @@ var MCP_STORE_AWARE_TOOLS = [
|
|
|
1943
2021
|
"fab_extract_knowledge",
|
|
1944
2022
|
"fab_review"
|
|
1945
2023
|
];
|
|
1946
|
-
var storeAwareEntrySchema =
|
|
1947
|
-
stable_id:
|
|
2024
|
+
var storeAwareEntrySchema = z11.object({
|
|
2025
|
+
stable_id: z11.string(),
|
|
1948
2026
|
global_ref: globalRefSchema,
|
|
1949
2027
|
provenance: knowledgeProvenanceSchema
|
|
1950
2028
|
}).strict();
|
|
1951
|
-
var writtenToStoreSchema =
|
|
2029
|
+
var writtenToStoreSchema = z11.object({
|
|
1952
2030
|
store_uuid: storeUuidSchema,
|
|
1953
|
-
alias:
|
|
2031
|
+
alias: z11.string().min(1)
|
|
1954
2032
|
}).strict();
|
|
1955
2033
|
var MCP_STORE_AWARE_CONTRACTS = {
|
|
1956
2034
|
fab_recall: { tool: "fab_recall", surfacesEntries: true, echoesWrittenStore: false },
|
|
@@ -1963,7 +2041,7 @@ var MCP_STORE_AWARE_CONTRACTS = {
|
|
|
1963
2041
|
fab_archive_scan: {
|
|
1964
2042
|
tool: "fab_archive_scan",
|
|
1965
2043
|
surfacesEntries: false,
|
|
1966
|
-
echoesWrittenStore:
|
|
2044
|
+
echoesWrittenStore: false
|
|
1967
2045
|
},
|
|
1968
2046
|
fab_extract_knowledge: {
|
|
1969
2047
|
tool: "fab_extract_knowledge",
|
|
@@ -1974,64 +2052,184 @@ var MCP_STORE_AWARE_CONTRACTS = {
|
|
|
1974
2052
|
};
|
|
1975
2053
|
|
|
1976
2054
|
// src/schemas/bindings-snapshot.ts
|
|
1977
|
-
import { z as
|
|
1978
|
-
var resolvedBindingsSnapshotSchema =
|
|
2055
|
+
import { z as z12 } from "zod";
|
|
2056
|
+
var resolvedBindingsSnapshotSchema = z12.object({
|
|
1979
2057
|
// Schema version of the snapshot document.
|
|
1980
|
-
version:
|
|
2058
|
+
version: z12.literal(1),
|
|
1981
2059
|
// The project this snapshot is bound to (S13).
|
|
1982
|
-
project_id:
|
|
2060
|
+
project_id: z12.string().min(1),
|
|
2061
|
+
// The local runtime binding key. Defaults to project_id for standard repos;
|
|
2062
|
+
// worktrees may isolate state by setting fabric-config.workspace_binding_id.
|
|
2063
|
+
workspace_binding_id: z12.string().min(1),
|
|
1983
2064
|
// ISO-8601 generation timestamp (provenance / staleness signal for doctor).
|
|
1984
|
-
generated_at:
|
|
2065
|
+
generated_at: z12.string().min(1),
|
|
1985
2066
|
// Pre-resolved read-set (required_stores ∪ implicit personal + warnings).
|
|
1986
2067
|
read_set: storeReadSetSchema,
|
|
1987
2068
|
// Pre-resolved active write target for non-personal scopes (null if none).
|
|
1988
|
-
write_target: writeTargetSchema.nullable()
|
|
2069
|
+
write_target: writeTargetSchema.nullable(),
|
|
2070
|
+
// Pre-computed store-backed knowledge counts, snapshotted at write time.
|
|
2071
|
+
// PROVENANCE ONLY: these are store-global counts cached in a per-workspace
|
|
2072
|
+
// file, so they go stale whenever store content changes out-of-band (a `git
|
|
2073
|
+
// pull` in the store repo, a sync run from a *different* bound workspace,
|
|
2074
|
+
// etc.) — the snapshot is only regenerated by install/sync/store-ops in the
|
|
2075
|
+
// workspace that runs them (KT-PIT-0017). Hooks MUST NOT trust these numbers
|
|
2076
|
+
// for nudges; they recount live from `knowledge_store_dirs`. Retained for
|
|
2077
|
+
// doctor provenance + backward-compatible fallback when dirs are absent.
|
|
2078
|
+
knowledge_stats: z12.object({
|
|
2079
|
+
pending_count: z12.number().int().nonnegative(),
|
|
2080
|
+
canonical_count: z12.number().int().nonnegative(),
|
|
2081
|
+
oldest_pending_mtime_ms: z12.number().nonnegative().nullable()
|
|
2082
|
+
}).strict().optional(),
|
|
2083
|
+
// Resolved absolute store ROOT dirs the knowledge_stats were derived from.
|
|
2084
|
+
// STABLE across content sync — they only change when mounts/bindings change,
|
|
2085
|
+
// which DOES regenerate the snapshot. Hooks walk `<dir>/knowledge/<type>` +
|
|
2086
|
+
// `<dir>/knowledge/pending` LIVE off these roots so nudge counts are always
|
|
2087
|
+
// fresh regardless of how store content changed (the underseed / review-
|
|
2088
|
+
// backlog false-positive root cure; pairs with knowledge_stats above).
|
|
2089
|
+
knowledge_store_dirs: z12.array(z12.string().min(1)).optional()
|
|
1989
2090
|
}).strict();
|
|
1990
2091
|
|
|
1991
2092
|
// src/store/bindings.ts
|
|
1992
|
-
import {
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
2093
|
+
import {
|
|
2094
|
+
existsSync as existsSync4,
|
|
2095
|
+
mkdirSync as mkdirSync2,
|
|
2096
|
+
readdirSync as readdirSync3,
|
|
2097
|
+
readFileSync as readFileSync4,
|
|
2098
|
+
renameSync,
|
|
2099
|
+
statSync,
|
|
2100
|
+
unlinkSync,
|
|
2101
|
+
writeFileSync as writeFileSync3
|
|
2102
|
+
} from "fs";
|
|
2103
|
+
import { join as join5, resolve, sep } from "path";
|
|
2104
|
+
var SAFE_BINDING_ID = /^[A-Za-z0-9._-]+$/;
|
|
2105
|
+
function assertSafeBindingId(bindingId) {
|
|
2106
|
+
if (!SAFE_BINDING_ID.test(bindingId) || bindingId.includes("..")) {
|
|
1997
2107
|
throw new Error(
|
|
1998
|
-
`bindingsSnapshotPath: refusing unsafe
|
|
2108
|
+
`bindingsSnapshotPath: refusing unsafe workspace_binding_id ${JSON.stringify(bindingId)} (must match ${SAFE_BINDING_ID} and contain no "..")`
|
|
1999
2109
|
);
|
|
2000
2110
|
}
|
|
2001
2111
|
}
|
|
2002
|
-
function bindingsSnapshotPath(globalRoot,
|
|
2003
|
-
|
|
2004
|
-
const bindingsDir = resolve(
|
|
2005
|
-
const path = resolve(
|
|
2112
|
+
function bindingsSnapshotPath(globalRoot, bindingId) {
|
|
2113
|
+
assertSafeBindingId(bindingId);
|
|
2114
|
+
const bindingsDir = resolve(join5(globalRoot, GLOBAL_STATE_DIR, GLOBAL_BINDINGS_DIR));
|
|
2115
|
+
const path = resolve(join5(bindingsDir, `${bindingId}_resolved.json`));
|
|
2006
2116
|
if (path !== bindingsDir && !path.startsWith(bindingsDir + sep)) {
|
|
2007
|
-
throw new Error(`bindingsSnapshotPath: resolved path escapes bindings dir for ${JSON.stringify(
|
|
2117
|
+
throw new Error(`bindingsSnapshotPath: resolved path escapes bindings dir for ${JSON.stringify(bindingId)}`);
|
|
2008
2118
|
}
|
|
2009
2119
|
return path;
|
|
2010
2120
|
}
|
|
2121
|
+
function resolveWorkspaceBindingId(config) {
|
|
2122
|
+
return config.workspace_binding_id ?? config.project_id;
|
|
2123
|
+
}
|
|
2124
|
+
function countMarkdownFiles(dir) {
|
|
2125
|
+
let count = 0;
|
|
2126
|
+
let oldestMtimeMs = null;
|
|
2127
|
+
if (!existsSync4(dir)) {
|
|
2128
|
+
return { count, oldestMtimeMs };
|
|
2129
|
+
}
|
|
2130
|
+
let entries;
|
|
2131
|
+
try {
|
|
2132
|
+
entries = readdirSync3(dir, { withFileTypes: true });
|
|
2133
|
+
} catch {
|
|
2134
|
+
return { count, oldestMtimeMs };
|
|
2135
|
+
}
|
|
2136
|
+
for (const entry of entries) {
|
|
2137
|
+
const fullPath = join5(dir, entry.name);
|
|
2138
|
+
if (entry.isDirectory()) {
|
|
2139
|
+
const nested = countMarkdownFiles(fullPath);
|
|
2140
|
+
count += nested.count;
|
|
2141
|
+
if (nested.oldestMtimeMs !== null && (oldestMtimeMs === null || nested.oldestMtimeMs < oldestMtimeMs)) {
|
|
2142
|
+
oldestMtimeMs = nested.oldestMtimeMs;
|
|
2143
|
+
}
|
|
2144
|
+
continue;
|
|
2145
|
+
}
|
|
2146
|
+
if (!entry.isFile() || !entry.name.endsWith(".md")) {
|
|
2147
|
+
continue;
|
|
2148
|
+
}
|
|
2149
|
+
let mtimeMs;
|
|
2150
|
+
try {
|
|
2151
|
+
mtimeMs = statSync(fullPath).mtimeMs;
|
|
2152
|
+
} catch {
|
|
2153
|
+
continue;
|
|
2154
|
+
}
|
|
2155
|
+
count += 1;
|
|
2156
|
+
if (oldestMtimeMs === null || mtimeMs < oldestMtimeMs) {
|
|
2157
|
+
oldestMtimeMs = mtimeMs;
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
return { count, oldestMtimeMs };
|
|
2161
|
+
}
|
|
2162
|
+
function collectKnowledgeStats(globalRoot, resolveInput, readSet) {
|
|
2163
|
+
let pendingCount = 0;
|
|
2164
|
+
let oldestPendingMtimeMs = null;
|
|
2165
|
+
let canonicalCount = 0;
|
|
2166
|
+
const storeDirs = [];
|
|
2167
|
+
for (const store of readSet.stores) {
|
|
2168
|
+
const mounted = resolveInput.mountedStores.find((entry) => entry.store_uuid === store.store_uuid) ?? {
|
|
2169
|
+
store_uuid: store.store_uuid
|
|
2170
|
+
};
|
|
2171
|
+
const storeDir = join5(globalRoot, storeRelativePathForMount(mounted));
|
|
2172
|
+
storeDirs.push(storeDir);
|
|
2173
|
+
for (const type of STORE_KNOWLEDGE_TYPE_DIRS) {
|
|
2174
|
+
const canonical = countMarkdownFiles(join5(storeDir, STORE_LAYOUT.knowledgeDir, type));
|
|
2175
|
+
canonicalCount += canonical.count;
|
|
2176
|
+
}
|
|
2177
|
+
const pending = countMarkdownFiles(join5(storeDir, STORE_LAYOUT.knowledgeDir, "pending"));
|
|
2178
|
+
pendingCount += pending.count;
|
|
2179
|
+
if (pending.oldestMtimeMs !== null && (oldestPendingMtimeMs === null || pending.oldestMtimeMs < oldestPendingMtimeMs)) {
|
|
2180
|
+
oldestPendingMtimeMs = pending.oldestMtimeMs;
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2183
|
+
return {
|
|
2184
|
+
stats: {
|
|
2185
|
+
pending_count: pendingCount,
|
|
2186
|
+
canonical_count: canonicalCount,
|
|
2187
|
+
oldest_pending_mtime_ms: oldestPendingMtimeMs
|
|
2188
|
+
},
|
|
2189
|
+
storeDirs
|
|
2190
|
+
};
|
|
2191
|
+
}
|
|
2192
|
+
function atomicWriteJsonSync(path, value) {
|
|
2193
|
+
const tmpPath = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
2194
|
+
try {
|
|
2195
|
+
writeFileSync3(tmpPath, `${JSON.stringify(value, null, 2)}
|
|
2196
|
+
`, "utf8");
|
|
2197
|
+
renameSync(tmpPath, path);
|
|
2198
|
+
} catch (error) {
|
|
2199
|
+
try {
|
|
2200
|
+
unlinkSync(tmpPath);
|
|
2201
|
+
} catch {
|
|
2202
|
+
}
|
|
2203
|
+
throw error;
|
|
2204
|
+
}
|
|
2205
|
+
}
|
|
2011
2206
|
function writeBindingsSnapshot(options) {
|
|
2012
2207
|
const resolver = createStoreResolver();
|
|
2013
2208
|
const read_set = resolver.resolveReadSet(options.resolveInput);
|
|
2014
2209
|
const { target } = resolver.resolveWriteTarget(options.resolveInput, options.writeScope);
|
|
2210
|
+
const { stats, storeDirs } = collectKnowledgeStats(options.globalRoot, options.resolveInput, read_set);
|
|
2015
2211
|
const snapshot = resolvedBindingsSnapshotSchema.parse({
|
|
2016
2212
|
version: 1,
|
|
2017
2213
|
project_id: options.projectId,
|
|
2214
|
+
workspace_binding_id: options.workspaceBindingId ?? options.projectId,
|
|
2018
2215
|
generated_at: options.now,
|
|
2019
2216
|
read_set,
|
|
2020
|
-
write_target: target
|
|
2217
|
+
write_target: target,
|
|
2218
|
+
knowledge_stats: stats,
|
|
2219
|
+
knowledge_store_dirs: storeDirs
|
|
2021
2220
|
});
|
|
2022
|
-
const path = bindingsSnapshotPath(options.globalRoot,
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
`, "utf8");
|
|
2221
|
+
const path = bindingsSnapshotPath(options.globalRoot, snapshot.workspace_binding_id);
|
|
2222
|
+
mkdirSync2(join5(path, ".."), { recursive: true });
|
|
2223
|
+
atomicWriteJsonSync(path, snapshot);
|
|
2026
2224
|
return snapshot;
|
|
2027
2225
|
}
|
|
2028
2226
|
function readBindingsSnapshot(globalRoot, projectId) {
|
|
2029
2227
|
const path = bindingsSnapshotPath(globalRoot, projectId);
|
|
2030
|
-
if (!
|
|
2228
|
+
if (!existsSync4(path)) {
|
|
2031
2229
|
return null;
|
|
2032
2230
|
}
|
|
2033
2231
|
try {
|
|
2034
|
-
const parsed = resolvedBindingsSnapshotSchema.safeParse(JSON.parse(
|
|
2232
|
+
const parsed = resolvedBindingsSnapshotSchema.safeParse(JSON.parse(readFileSync4(path, "utf8")));
|
|
2035
2233
|
return parsed.success ? parsed.data : null;
|
|
2036
2234
|
} catch {
|
|
2037
2235
|
return null;
|
|
@@ -2040,7 +2238,9 @@ function readBindingsSnapshot(globalRoot, projectId) {
|
|
|
2040
2238
|
|
|
2041
2239
|
// src/store/store-lifecycle.ts
|
|
2042
2240
|
function findMountedStore(config, aliasOrUuid) {
|
|
2043
|
-
return config.stores.find(
|
|
2241
|
+
return config.stores.find(
|
|
2242
|
+
(s) => s.alias === aliasOrUuid || s.store_uuid === aliasOrUuid || s.mount_name === aliasOrUuid
|
|
2243
|
+
);
|
|
2044
2244
|
}
|
|
2045
2245
|
function addMountedStore(config, store) {
|
|
2046
2246
|
const aliasClash = config.stores.find(
|
|
@@ -2051,12 +2251,32 @@ function addMountedStore(config, store) {
|
|
|
2051
2251
|
`alias '${store.alias}' already mounts store ${aliasClash.store_uuid}; choose another alias`
|
|
2052
2252
|
);
|
|
2053
2253
|
}
|
|
2254
|
+
const mountNameClash = store.mount_name === void 0 ? void 0 : config.stores.find(
|
|
2255
|
+
(s) => s.mount_name === store.mount_name && s.store_uuid !== store.store_uuid
|
|
2256
|
+
);
|
|
2257
|
+
if (mountNameClash !== void 0) {
|
|
2258
|
+
throw new Error(
|
|
2259
|
+
`mount_name '${store.mount_name}' already maps to store ${mountNameClash.store_uuid}; choose another mount_name`
|
|
2260
|
+
);
|
|
2261
|
+
}
|
|
2054
2262
|
const sanitized = store.remote === void 0 ? store : { ...store, remote: scrubRemoteUrl(store.remote) };
|
|
2055
2263
|
store = sanitized;
|
|
2056
2264
|
const existing = config.stores.find((s) => s.store_uuid === store.store_uuid);
|
|
2057
2265
|
const stores = existing === void 0 ? [...config.stores, store] : config.stores.map((s) => s.store_uuid === store.store_uuid ? store : s);
|
|
2058
2266
|
return { ...config, stores };
|
|
2059
2267
|
}
|
|
2268
|
+
function disambiguateAlias(existingAliases, desired) {
|
|
2269
|
+
const taken = new Set(existingAliases);
|
|
2270
|
+
if (!taken.has(desired)) {
|
|
2271
|
+
return desired;
|
|
2272
|
+
}
|
|
2273
|
+
for (let n = 2; ; n += 1) {
|
|
2274
|
+
const candidate = `${desired}-${n}`;
|
|
2275
|
+
if (!taken.has(candidate)) {
|
|
2276
|
+
return candidate;
|
|
2277
|
+
}
|
|
2278
|
+
}
|
|
2279
|
+
}
|
|
2060
2280
|
function detachMountedStore(config, alias) {
|
|
2061
2281
|
const detached = config.stores.find((s) => s.alias === alias) ?? null;
|
|
2062
2282
|
if (detached === null) {
|
|
@@ -2085,155 +2305,155 @@ function explainStore(config, alias) {
|
|
|
2085
2305
|
}
|
|
2086
2306
|
|
|
2087
2307
|
// 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:
|
|
2308
|
+
import { z as z13 } from "zod";
|
|
2309
|
+
var forensicCodeSampleSchema = z13.object({
|
|
2310
|
+
path: z13.string(),
|
|
2311
|
+
lines: z13.string(),
|
|
2312
|
+
snippet: z13.string(),
|
|
2313
|
+
pattern_hint: z13.string()
|
|
2314
|
+
});
|
|
2315
|
+
var forensicEvidenceAnchorSchema = z13.object({
|
|
2316
|
+
file: z13.string(),
|
|
2317
|
+
line: z13.string(),
|
|
2318
|
+
snippet: z13.string()
|
|
2319
|
+
});
|
|
2320
|
+
var forensicAssertionCoverageSchema = z13.object({
|
|
2321
|
+
ratio: z13.number().min(0).max(1),
|
|
2322
|
+
total: z13.number().int().nonnegative(),
|
|
2323
|
+
matched: z13.number().int().nonnegative(),
|
|
2324
|
+
co_occurring_patterns: z13.array(z13.string())
|
|
2325
|
+
});
|
|
2326
|
+
var forensicAssertionSchema = z13.object({
|
|
2327
|
+
type: z13.enum(["framework", "pattern", "invariant", "domain"]),
|
|
2328
|
+
statement: z13.string(),
|
|
2329
|
+
confidence: z13.enum(["HIGH", "MEDIUM", "LOW"]),
|
|
2330
|
+
evidence: z13.array(forensicEvidenceAnchorSchema),
|
|
2111
2331
|
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:
|
|
2332
|
+
proposed_rule: z13.string().optional(),
|
|
2333
|
+
alternatives: z13.array(z13.string()).optional()
|
|
2334
|
+
});
|
|
2335
|
+
var forensicTopologySchema = z13.object({
|
|
2336
|
+
total_files: z13.number().int().nonnegative(),
|
|
2337
|
+
by_ext: z13.record(z13.number().int().nonnegative()),
|
|
2338
|
+
key_dirs: z13.array(z13.string()),
|
|
2339
|
+
max_depth: z13.number().int().nonnegative()
|
|
2340
|
+
});
|
|
2341
|
+
var forensicEntryPointSchema = z13.object({
|
|
2342
|
+
path: z13.string(),
|
|
2343
|
+
reason: z13.string(),
|
|
2344
|
+
size_bytes: z13.number().int().nonnegative().optional()
|
|
2345
|
+
});
|
|
2346
|
+
var forensicFrameworkSchema = z13.object({
|
|
2347
|
+
kind: z13.string(),
|
|
2348
|
+
version: z13.string(),
|
|
2349
|
+
subkind: z13.string(),
|
|
2350
|
+
evidence: z13.array(z13.string())
|
|
2351
|
+
});
|
|
2352
|
+
var forensicReadmeSchema = z13.object({
|
|
2353
|
+
quality: z13.enum(["missing", "stub", "ok"]),
|
|
2354
|
+
line_count: z13.number().int().nonnegative(),
|
|
2355
|
+
has_contributing: z13.boolean()
|
|
2356
|
+
});
|
|
2357
|
+
var candidateFileEntrySchema = z13.object({
|
|
2358
|
+
path: z13.string(),
|
|
2359
|
+
family: z13.enum(["entry", "component", "config", "test", "domain"]),
|
|
2360
|
+
rationale: z13.string()
|
|
2361
|
+
});
|
|
2362
|
+
var forensicSamplingBudgetSchema = z13.object({
|
|
2363
|
+
max_files: z13.literal(15),
|
|
2364
|
+
max_lines_per_file: z13.literal(100)
|
|
2365
|
+
});
|
|
2366
|
+
var forensicReportSchema = z13.object({
|
|
2367
|
+
version: z13.string(),
|
|
2368
|
+
generated_at: z13.string(),
|
|
2369
|
+
generated_by: z13.string(),
|
|
2370
|
+
target: z13.string(),
|
|
2371
|
+
project_name: z13.string(),
|
|
2152
2372
|
framework: forensicFrameworkSchema,
|
|
2153
2373
|
topology: forensicTopologySchema,
|
|
2154
|
-
entry_points:
|
|
2155
|
-
code_samples:
|
|
2156
|
-
assertions:
|
|
2157
|
-
candidate_files:
|
|
2374
|
+
entry_points: z13.array(forensicEntryPointSchema),
|
|
2375
|
+
code_samples: z13.array(forensicCodeSampleSchema),
|
|
2376
|
+
assertions: z13.array(forensicAssertionSchema),
|
|
2377
|
+
candidate_files: z13.array(candidateFileEntrySchema),
|
|
2158
2378
|
sampling_budget: forensicSamplingBudgetSchema,
|
|
2159
2379
|
readme: forensicReadmeSchema,
|
|
2160
|
-
recommendations_for_skill:
|
|
2380
|
+
recommendations_for_skill: z13.array(z13.string()).optional()
|
|
2161
2381
|
});
|
|
2162
2382
|
|
|
2163
2383
|
// 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:
|
|
2384
|
+
import { z as z14 } from "zod";
|
|
2385
|
+
var initContextFrameworkSchema = z14.object({
|
|
2386
|
+
kind: z14.string(),
|
|
2387
|
+
version: z14.string(),
|
|
2388
|
+
subkind: z14.string()
|
|
2389
|
+
});
|
|
2390
|
+
var initContextInvariantConfidenceSnapshotSchema = z14.object({
|
|
2391
|
+
confidence: z14.enum(["HIGH", "MEDIUM", "LOW"]),
|
|
2392
|
+
evidence_refs: z14.array(z14.string())
|
|
2393
|
+
});
|
|
2394
|
+
var initContextSourceEvidenceSchema = z14.object({
|
|
2395
|
+
file: z14.string(),
|
|
2396
|
+
lines: z14.string()
|
|
2397
|
+
});
|
|
2398
|
+
var initContextInvariantSchema = z14.object({
|
|
2399
|
+
type: z14.enum(["ban", "require", "protect"]),
|
|
2400
|
+
rule: z14.string(),
|
|
2401
|
+
rationale: z14.string().optional(),
|
|
2182
2402
|
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 =
|
|
2403
|
+
source_evidence: z14.array(initContextSourceEvidenceSchema).optional()
|
|
2404
|
+
});
|
|
2405
|
+
var initContextDomainGroupSchema = z14.object({
|
|
2406
|
+
name: z14.string(),
|
|
2407
|
+
paths: z14.array(z14.string()),
|
|
2408
|
+
summary: z14.string().optional(),
|
|
2409
|
+
topology_type: z14.enum(["mirror", "cross-cutting"]).optional(),
|
|
2410
|
+
target_path: z14.string().optional()
|
|
2411
|
+
});
|
|
2412
|
+
var initContextInterviewTrailEntrySchema = z14.object({
|
|
2413
|
+
phase: z14.string(),
|
|
2414
|
+
question: z14.string(),
|
|
2415
|
+
answer: z14.string(),
|
|
2416
|
+
presentation: z14.string().optional(),
|
|
2417
|
+
user_corrections: z14.array(z14.string()).optional()
|
|
2418
|
+
});
|
|
2419
|
+
var initContextSchema = z14.object({
|
|
2200
2420
|
framework: initContextFrameworkSchema,
|
|
2201
|
-
architecture_patterns:
|
|
2202
|
-
invariants:
|
|
2203
|
-
domain_groups:
|
|
2204
|
-
interview_trail:
|
|
2205
|
-
forensic_ref:
|
|
2421
|
+
architecture_patterns: z14.array(z14.string()),
|
|
2422
|
+
invariants: z14.array(initContextInvariantSchema),
|
|
2423
|
+
domain_groups: z14.array(initContextDomainGroupSchema),
|
|
2424
|
+
interview_trail: z14.array(initContextInterviewTrailEntrySchema),
|
|
2425
|
+
forensic_ref: z14.string()
|
|
2206
2426
|
});
|
|
2207
2427
|
|
|
2208
2428
|
// src/schemas/events.ts
|
|
2209
|
-
import { z as
|
|
2210
|
-
var metaUpdatedEventSchema =
|
|
2211
|
-
type:
|
|
2429
|
+
import { z as z15 } from "zod";
|
|
2430
|
+
var metaUpdatedEventSchema = z15.object({
|
|
2431
|
+
type: z15.literal("meta:updated"),
|
|
2212
2432
|
payload: agentsMetaSchema
|
|
2213
2433
|
});
|
|
2214
|
-
var lockDriftEventSchema =
|
|
2215
|
-
type:
|
|
2216
|
-
payload:
|
|
2217
|
-
locked:
|
|
2218
|
-
drifted:
|
|
2434
|
+
var lockDriftEventSchema = z15.object({
|
|
2435
|
+
type: z15.literal("lock:drift"),
|
|
2436
|
+
payload: z15.object({
|
|
2437
|
+
locked: z15.array(humanLockEntrySchema),
|
|
2438
|
+
drifted: z15.array(humanLockEntrySchema)
|
|
2219
2439
|
})
|
|
2220
2440
|
});
|
|
2221
|
-
var lockApprovedEventSchema =
|
|
2222
|
-
type:
|
|
2223
|
-
payload:
|
|
2224
|
-
locked:
|
|
2225
|
-
approved:
|
|
2441
|
+
var lockApprovedEventSchema = z15.object({
|
|
2442
|
+
type: z15.literal("lock:approved"),
|
|
2443
|
+
payload: z15.object({
|
|
2444
|
+
locked: z15.array(humanLockEntrySchema),
|
|
2445
|
+
approved: z15.array(humanLockEntrySchema)
|
|
2226
2446
|
})
|
|
2227
2447
|
});
|
|
2228
|
-
var ledgerAppendedEventSchema =
|
|
2229
|
-
type:
|
|
2448
|
+
var ledgerAppendedEventSchema = z15.object({
|
|
2449
|
+
type: z15.literal("ledger:appended"),
|
|
2230
2450
|
payload: ledgerEntrySchema
|
|
2231
2451
|
});
|
|
2232
|
-
var driftDetectedEventSchema =
|
|
2233
|
-
type:
|
|
2452
|
+
var driftDetectedEventSchema = z15.object({
|
|
2453
|
+
type: z15.literal("drift:detected"),
|
|
2234
2454
|
payload: forensicReportSchema
|
|
2235
2455
|
});
|
|
2236
|
-
var fabricEventSchema =
|
|
2456
|
+
var fabricEventSchema = z15.discriminatedUnion("type", [
|
|
2237
2457
|
metaUpdatedEventSchema,
|
|
2238
2458
|
lockDriftEventSchema,
|
|
2239
2459
|
lockApprovedEventSchema,
|
|
@@ -2242,7 +2462,7 @@ var fabricEventSchema = z17.discriminatedUnion("type", [
|
|
|
2242
2462
|
]);
|
|
2243
2463
|
|
|
2244
2464
|
// src/schemas/event-ledger.ts
|
|
2245
|
-
import { z as
|
|
2465
|
+
import { z as z16 } from "zod";
|
|
2246
2466
|
|
|
2247
2467
|
// src/cite-line-parser.ts
|
|
2248
2468
|
var ID_RE = /^K[TP]-[A-Z]+-\d+$/;
|
|
@@ -2256,17 +2476,12 @@ function splitStorePrefix(token) {
|
|
|
2256
2476
|
return colon === -1 ? { store: null, id: token } : { store: token.slice(0, colon), id: token.slice(colon + 1) };
|
|
2257
2477
|
}
|
|
2258
2478
|
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
2479
|
function normalizeCiteTag(rawTag) {
|
|
2265
2480
|
const head = rawTag.trim().split(/[\s:]+/)[0].toLowerCase();
|
|
2266
2481
|
if (head === "applied" || head === "dismissed" || head === "none") {
|
|
2267
2482
|
return head;
|
|
2268
2483
|
}
|
|
2269
|
-
return
|
|
2484
|
+
return "none";
|
|
2270
2485
|
}
|
|
2271
2486
|
function parseTag(rawTag) {
|
|
2272
2487
|
if (!rawTag) return "none";
|
|
@@ -2354,146 +2569,131 @@ function parseCiteLine(raw) {
|
|
|
2354
2569
|
}
|
|
2355
2570
|
|
|
2356
2571
|
// src/schemas/event-ledger.ts
|
|
2357
|
-
var citeTagSchema =
|
|
2572
|
+
var citeTagSchema = z16.preprocess(
|
|
2358
2573
|
(value) => typeof value === "string" ? normalizeCiteTag(value) : value,
|
|
2359
|
-
|
|
2574
|
+
z16.enum(["applied", "dismissed", "none"])
|
|
2360
2575
|
);
|
|
2361
2576
|
var eventLedgerEnvelopeSchema = {
|
|
2362
|
-
kind:
|
|
2363
|
-
id:
|
|
2364
|
-
ts:
|
|
2365
|
-
schema_version:
|
|
2366
|
-
correlation_id:
|
|
2367
|
-
session_id:
|
|
2577
|
+
kind: z16.literal("fabric-event"),
|
|
2578
|
+
id: z16.string(),
|
|
2579
|
+
ts: z16.number().int().nonnegative(),
|
|
2580
|
+
schema_version: z16.literal(1),
|
|
2581
|
+
correlation_id: z16.string().optional(),
|
|
2582
|
+
session_id: z16.string().optional()
|
|
2368
2583
|
};
|
|
2369
|
-
var stringRecordSchema =
|
|
2370
|
-
var knowledgeContextPlannedEventSchema =
|
|
2584
|
+
var stringRecordSchema = z16.record(z16.string());
|
|
2585
|
+
var knowledgeContextPlannedEventSchema = z16.object({
|
|
2371
2586
|
...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 =
|
|
2587
|
+
event_type: z16.literal("knowledge_context_planned"),
|
|
2588
|
+
target_paths: z16.array(z16.string()),
|
|
2589
|
+
required_stable_ids: z16.array(z16.string()),
|
|
2590
|
+
ai_selectable_stable_ids: z16.array(z16.string()),
|
|
2591
|
+
final_stable_ids: z16.array(z16.string()),
|
|
2592
|
+
selection_token: z16.string().optional(),
|
|
2593
|
+
client_hash: z16.string().optional(),
|
|
2594
|
+
intent: z16.string().optional(),
|
|
2595
|
+
known_tech: z16.array(z16.string()).optional(),
|
|
2596
|
+
diagnostics: z16.array(z16.unknown()).optional()
|
|
2597
|
+
});
|
|
2598
|
+
var knowledgeSelectionEventSchema = z16.object({
|
|
2384
2599
|
...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:
|
|
2600
|
+
event_type: z16.literal("knowledge_selection"),
|
|
2601
|
+
selection_token: z16.string(),
|
|
2602
|
+
target_paths: z16.array(z16.string()),
|
|
2603
|
+
required_stable_ids: z16.array(z16.string()),
|
|
2604
|
+
ai_selectable_stable_ids: z16.array(z16.string()),
|
|
2605
|
+
ai_selected_stable_ids: z16.array(z16.string()),
|
|
2606
|
+
final_stable_ids: z16.array(z16.string()),
|
|
2392
2607
|
ai_selection_reasons: stringRecordSchema,
|
|
2393
|
-
rejected_stable_ids:
|
|
2394
|
-
ignored_stable_ids:
|
|
2608
|
+
rejected_stable_ids: z16.array(z16.string()),
|
|
2609
|
+
ignored_stable_ids: z16.array(z16.string())
|
|
2395
2610
|
});
|
|
2396
|
-
var knowledgeSectionsFetchedEventSchema =
|
|
2611
|
+
var knowledgeSectionsFetchedEventSchema = z16.object({
|
|
2397
2612
|
...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 =
|
|
2613
|
+
event_type: z16.literal("knowledge_sections_fetched"),
|
|
2614
|
+
selection_token: z16.string(),
|
|
2615
|
+
target_paths: z16.array(z16.string()).optional(),
|
|
2616
|
+
requested_sections: z16.array(z16.string()),
|
|
2617
|
+
final_stable_ids: z16.array(z16.string()),
|
|
2618
|
+
ai_selected_stable_ids: z16.array(z16.string()),
|
|
2619
|
+
diagnostics: z16.array(z16.unknown()).optional()
|
|
2620
|
+
});
|
|
2621
|
+
var editIntentCheckedEventSchema = z16.object({
|
|
2407
2622
|
...eventLedgerEnvelopeSchema,
|
|
2408
|
-
event_type:
|
|
2409
|
-
path:
|
|
2410
|
-
compliant:
|
|
2411
|
-
intent:
|
|
2412
|
-
ledger_entry_id:
|
|
2623
|
+
event_type: z16.literal("edit_intent_checked"),
|
|
2624
|
+
path: z16.string(),
|
|
2625
|
+
compliant: z16.boolean(),
|
|
2626
|
+
intent: z16.string(),
|
|
2627
|
+
ledger_entry_id: z16.string(),
|
|
2413
2628
|
// rc.35 TASK-07 (P0-2): add "hook" — emitted by the PreToolUse narrow hook
|
|
2414
2629
|
// for every Edit/Write/MultiEdit fire so cite-coverage doctor metrics see
|
|
2415
2630
|
// actual edit signals (previously editsTouched was permanently 0 because
|
|
2416
2631
|
// 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 =
|
|
2632
|
+
ledger_source: z16.enum(["ai", "human", "hook"]).optional(),
|
|
2633
|
+
commit_sha: z16.string().optional(),
|
|
2634
|
+
parent_sha: z16.string().optional(),
|
|
2635
|
+
parent_ledger_entry_id: z16.string().optional(),
|
|
2636
|
+
diff_stat: z16.string().optional(),
|
|
2637
|
+
annotation: z16.string().optional(),
|
|
2638
|
+
matched_rule_context_ts: z16.number().int().nonnegative().nullable(),
|
|
2639
|
+
window_ms: z16.number().int().nonnegative()
|
|
2640
|
+
});
|
|
2641
|
+
var knowledgeDriftDetectedEventSchema = z16.object({
|
|
2427
2642
|
...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:
|
|
2643
|
+
event_type: z16.literal("knowledge_drift_detected"),
|
|
2644
|
+
revision: z16.string().optional(),
|
|
2645
|
+
drifted_stable_ids: z16.array(z16.string()),
|
|
2646
|
+
missing_files: z16.array(z16.string()),
|
|
2647
|
+
stale_files: z16.array(z16.string()),
|
|
2648
|
+
details: z16.array(
|
|
2649
|
+
z16.object({
|
|
2650
|
+
file: z16.string(),
|
|
2651
|
+
stable_id: z16.string(),
|
|
2652
|
+
expected_hash: z16.string(),
|
|
2653
|
+
actual_hash: z16.string().nullable()
|
|
2439
2654
|
})
|
|
2440
2655
|
).optional()
|
|
2441
2656
|
});
|
|
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({
|
|
2657
|
+
var mcpEventLedgerEventSchema = z16.object({
|
|
2450
2658
|
...eventLedgerEnvelopeSchema,
|
|
2451
|
-
event_type:
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2659
|
+
event_type: z16.literal("mcp_event"),
|
|
2660
|
+
mcp_event_id: z16.string(),
|
|
2661
|
+
stream_id: z16.string(),
|
|
2662
|
+
message: z16.unknown()
|
|
2455
2663
|
});
|
|
2456
|
-
var
|
|
2664
|
+
var reapplyCompletedEventSchema = z16.object({
|
|
2457
2665
|
...eventLedgerEnvelopeSchema,
|
|
2458
|
-
event_type:
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2666
|
+
event_type: z16.literal("reapply_completed"),
|
|
2667
|
+
preserved_ledger: z16.boolean(),
|
|
2668
|
+
preserved_meta: z16.boolean(),
|
|
2669
|
+
rules_count: z16.number().int().nonnegative()
|
|
2462
2670
|
});
|
|
2463
|
-
var
|
|
2671
|
+
var installDiffAppliedEventSchema = z16.object({
|
|
2464
2672
|
...eventLedgerEnvelopeSchema,
|
|
2465
|
-
event_type:
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2673
|
+
event_type: z16.literal("install_diff_applied"),
|
|
2674
|
+
applied: z16.array(z16.string()),
|
|
2675
|
+
canonical: z16.array(z16.string()),
|
|
2676
|
+
drifted: z16.array(z16.string())
|
|
2469
2677
|
});
|
|
2470
|
-
var
|
|
2678
|
+
var eventLedgerTruncatedEventSchema = z16.object({
|
|
2471
2679
|
...eventLedgerEnvelopeSchema,
|
|
2472
|
-
event_type:
|
|
2473
|
-
|
|
2474
|
-
|
|
2680
|
+
event_type: z16.literal("event_ledger_truncated"),
|
|
2681
|
+
byte_offset: z16.number().int().nonnegative(),
|
|
2682
|
+
byte_length: z16.number().int().nonnegative(),
|
|
2683
|
+
corrupted_path: z16.string()
|
|
2475
2684
|
});
|
|
2476
|
-
var
|
|
2477
|
-
...eventLedgerEnvelopeSchema,
|
|
2478
|
-
event_type: z18.literal("bootstrap_marker_migrated"),
|
|
2479
|
-
path: z18.string(),
|
|
2480
|
-
migrated_count: z18.number().int().nonnegative(),
|
|
2481
|
-
legacy_marker: z18.literal("fabric:knowledge-base"),
|
|
2482
|
-
new_marker: z18.literal("fabric:bootstrap"),
|
|
2483
|
-
timestamp: z18.string()
|
|
2484
|
-
});
|
|
2485
|
-
var metaReconciledOnStartupEventSchema = z18.object({
|
|
2685
|
+
var metaReconciledOnStartupEventSchema = z16.object({
|
|
2486
2686
|
...eventLedgerEnvelopeSchema,
|
|
2487
|
-
event_type:
|
|
2488
|
-
reconciled_files:
|
|
2489
|
-
duration_ms:
|
|
2490
|
-
source:
|
|
2687
|
+
event_type: z16.literal("meta_reconciled_on_startup"),
|
|
2688
|
+
reconciled_files: z16.array(z16.string()),
|
|
2689
|
+
duration_ms: z16.number().int().nonnegative(),
|
|
2690
|
+
source: z16.literal("reconcileKnowledge")
|
|
2491
2691
|
});
|
|
2492
|
-
var metaReconciledEventSchema =
|
|
2692
|
+
var metaReconciledEventSchema = z16.object({
|
|
2493
2693
|
...eventLedgerEnvelopeSchema,
|
|
2494
|
-
event_type:
|
|
2495
|
-
reconciled_files:
|
|
2496
|
-
duration_ms:
|
|
2694
|
+
event_type: z16.literal("meta_reconciled"),
|
|
2695
|
+
reconciled_files: z16.array(z16.string()),
|
|
2696
|
+
duration_ms: z16.number().int().nonnegative(),
|
|
2497
2697
|
// v2.0.0-rc.23 TASK-005 (a-B): added `auto-heal-description` trigger so the
|
|
2498
2698
|
// read-path plan_context handler can drive a full reconcile when it detects
|
|
2499
2699
|
// any node carrying `description === undefined` (legacy meta drift that the
|
|
@@ -2507,7 +2707,7 @@ var metaReconciledEventSchema = z18.object({
|
|
|
2507
2707
|
// v2.0.0-rc.29 TASK-005 (BUG-G1): `auto-heal-after-drift` added so
|
|
2508
2708
|
// `ensureKnowledgeFresh` hot-path can chain a paired reconcile (closing the
|
|
2509
2709
|
// drift→heal gap) when the caller opts in via `autoHealOnDrift: true`.
|
|
2510
|
-
trigger:
|
|
2710
|
+
trigger: z16.enum([
|
|
2511
2711
|
"doctor",
|
|
2512
2712
|
"manual",
|
|
2513
2713
|
"auto-heal-description",
|
|
@@ -2515,195 +2715,207 @@ var metaReconciledEventSchema = z18.object({
|
|
|
2515
2715
|
"post-approve",
|
|
2516
2716
|
"post-modify"
|
|
2517
2717
|
]),
|
|
2518
|
-
source:
|
|
2718
|
+
source: z16.literal("reconcileKnowledge"),
|
|
2519
2719
|
// v2.0.0-rc.22 TASK-014 (Scope E): set when reconcileKnowledge forced a
|
|
2520
2720
|
// writeKnowledgeMeta on revision drift alone (no per-file content drift).
|
|
2521
2721
|
// Distinguishes top-level schema/revision repair from the standard per-file
|
|
2522
2722
|
// drift path. Optional so existing emitters stay unchanged.
|
|
2523
|
-
force_write_reason:
|
|
2723
|
+
force_write_reason: z16.enum(["revision_drift"]).optional()
|
|
2524
2724
|
});
|
|
2525
|
-
var claudeSkillPathMigratedEventSchema =
|
|
2725
|
+
var claudeSkillPathMigratedEventSchema = z16.object({
|
|
2526
2726
|
...eventLedgerEnvelopeSchema,
|
|
2527
|
-
event_type:
|
|
2528
|
-
from:
|
|
2529
|
-
to:
|
|
2727
|
+
event_type: z16.literal("claude_skill_path_migrated"),
|
|
2728
|
+
from: z16.string(),
|
|
2729
|
+
to: z16.string()
|
|
2530
2730
|
});
|
|
2531
|
-
var claudeHookPathMigratedEventSchema =
|
|
2731
|
+
var claudeHookPathMigratedEventSchema = z16.object({
|
|
2532
2732
|
...eventLedgerEnvelopeSchema,
|
|
2533
|
-
event_type:
|
|
2534
|
-
from:
|
|
2535
|
-
to:
|
|
2733
|
+
event_type: z16.literal("claude_hook_path_migrated"),
|
|
2734
|
+
from: z16.string(),
|
|
2735
|
+
to: z16.string()
|
|
2536
2736
|
});
|
|
2537
|
-
var codexSkillPathMigratedEventSchema =
|
|
2737
|
+
var codexSkillPathMigratedEventSchema = z16.object({
|
|
2538
2738
|
...eventLedgerEnvelopeSchema,
|
|
2539
|
-
event_type:
|
|
2540
|
-
from:
|
|
2541
|
-
to:
|
|
2739
|
+
event_type: z16.literal("codex_skill_path_migrated"),
|
|
2740
|
+
from: z16.string(),
|
|
2741
|
+
to: z16.string()
|
|
2542
2742
|
});
|
|
2543
|
-
var initScanCompletedEventSchema =
|
|
2743
|
+
var initScanCompletedEventSchema = z16.object({
|
|
2544
2744
|
...eventLedgerEnvelopeSchema,
|
|
2545
|
-
event_type:
|
|
2546
|
-
written_stable_ids:
|
|
2547
|
-
duration_ms:
|
|
2548
|
-
source:
|
|
2745
|
+
event_type: z16.literal("init_scan_completed"),
|
|
2746
|
+
written_stable_ids: z16.array(z16.string()),
|
|
2747
|
+
duration_ms: z16.number().int().nonnegative(),
|
|
2748
|
+
source: z16.enum(["init", "scan", "doctor_fix", "doctor-rescan"]).optional()
|
|
2549
2749
|
});
|
|
2550
|
-
var knowledgeProposedEventSchema =
|
|
2750
|
+
var knowledgeProposedEventSchema = z16.object({
|
|
2551
2751
|
...eventLedgerEnvelopeSchema,
|
|
2552
|
-
event_type:
|
|
2553
|
-
stable_id:
|
|
2554
|
-
timestamp:
|
|
2555
|
-
reason:
|
|
2752
|
+
event_type: z16.literal("knowledge_proposed"),
|
|
2753
|
+
stable_id: z16.string().optional(),
|
|
2754
|
+
timestamp: z16.string().datetime(),
|
|
2755
|
+
reason: z16.string().optional()
|
|
2556
2756
|
});
|
|
2557
|
-
var knowledgePromoteStartedEventSchema =
|
|
2757
|
+
var knowledgePromoteStartedEventSchema = z16.object({
|
|
2558
2758
|
...eventLedgerEnvelopeSchema,
|
|
2559
|
-
event_type:
|
|
2560
|
-
stable_id:
|
|
2561
|
-
timestamp:
|
|
2562
|
-
reason:
|
|
2759
|
+
event_type: z16.literal("knowledge_promote_started"),
|
|
2760
|
+
stable_id: z16.string().optional(),
|
|
2761
|
+
timestamp: z16.string().datetime(),
|
|
2762
|
+
reason: z16.string().optional()
|
|
2563
2763
|
});
|
|
2564
|
-
var knowledgePromotedEventSchema =
|
|
2764
|
+
var knowledgePromotedEventSchema = z16.object({
|
|
2565
2765
|
...eventLedgerEnvelopeSchema,
|
|
2566
|
-
event_type:
|
|
2567
|
-
stable_id:
|
|
2568
|
-
timestamp:
|
|
2569
|
-
reason:
|
|
2766
|
+
event_type: z16.literal("knowledge_promoted"),
|
|
2767
|
+
stable_id: z16.string().optional(),
|
|
2768
|
+
timestamp: z16.string().datetime(),
|
|
2769
|
+
reason: z16.string().optional()
|
|
2570
2770
|
});
|
|
2571
|
-
var knowledgePromoteFailedEventSchema =
|
|
2771
|
+
var knowledgePromoteFailedEventSchema = z16.object({
|
|
2572
2772
|
...eventLedgerEnvelopeSchema,
|
|
2573
|
-
event_type:
|
|
2574
|
-
stable_id:
|
|
2575
|
-
timestamp:
|
|
2576
|
-
reason:
|
|
2773
|
+
event_type: z16.literal("knowledge_promote_failed"),
|
|
2774
|
+
stable_id: z16.string().optional(),
|
|
2775
|
+
timestamp: z16.string().datetime(),
|
|
2776
|
+
reason: z16.string()
|
|
2577
2777
|
});
|
|
2578
|
-
var
|
|
2778
|
+
var knowledgeModifiedEventSchema = z16.object({
|
|
2579
2779
|
...eventLedgerEnvelopeSchema,
|
|
2580
|
-
event_type:
|
|
2581
|
-
stable_id:
|
|
2582
|
-
timestamp:
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2780
|
+
event_type: z16.literal("knowledge_modified"),
|
|
2781
|
+
stable_id: z16.string().optional(),
|
|
2782
|
+
timestamp: z16.string().datetime(),
|
|
2783
|
+
path: z16.string(),
|
|
2784
|
+
changed_fields: z16.array(z16.string()),
|
|
2785
|
+
before: z16.record(z16.unknown()),
|
|
2786
|
+
after: z16.record(z16.unknown()),
|
|
2787
|
+
reason: z16.string().optional()
|
|
2788
|
+
});
|
|
2789
|
+
var knowledgeLayerChangedEventSchema = z16.object({
|
|
2790
|
+
...eventLedgerEnvelopeSchema,
|
|
2791
|
+
event_type: z16.literal("knowledge_layer_changed"),
|
|
2792
|
+
stable_id: z16.string().optional(),
|
|
2793
|
+
timestamp: z16.string().datetime(),
|
|
2794
|
+
reason: z16.string().optional(),
|
|
2795
|
+
from_layer: z16.enum(["team", "personal"]),
|
|
2796
|
+
to_layer: z16.enum(["team", "personal"]),
|
|
2586
2797
|
// v2.0.0-rc.37 NEW-24: record the pre-flip stable_id so downstream consumers
|
|
2587
2798
|
// (fab_plan_context redirect surface, fab_get_knowledge_sections.redirect_to)
|
|
2588
2799
|
// can map a stale caller-held id back to the post-flip canonical id without
|
|
2589
2800
|
// requiring the caller to re-issue plan-context. Optional for forward-
|
|
2590
2801
|
// compatibility with rc ≤36 events that never carried this field.
|
|
2591
|
-
previous_stable_id:
|
|
2802
|
+
previous_stable_id: z16.string().optional()
|
|
2592
2803
|
});
|
|
2593
|
-
var knowledgeIdRedirectEventSchema =
|
|
2804
|
+
var knowledgeIdRedirectEventSchema = z16.object({
|
|
2594
2805
|
...eventLedgerEnvelopeSchema,
|
|
2595
|
-
event_type:
|
|
2596
|
-
timestamp:
|
|
2597
|
-
previous_stable_id:
|
|
2598
|
-
new_stable_id:
|
|
2599
|
-
reason:
|
|
2806
|
+
event_type: z16.literal("knowledge_id_redirect"),
|
|
2807
|
+
timestamp: z16.string().datetime(),
|
|
2808
|
+
previous_stable_id: z16.string(),
|
|
2809
|
+
new_stable_id: z16.string(),
|
|
2810
|
+
reason: z16.string().optional()
|
|
2600
2811
|
});
|
|
2601
|
-
var knowledgeSlugRenamedEventSchema =
|
|
2812
|
+
var knowledgeSlugRenamedEventSchema = z16.object({
|
|
2602
2813
|
...eventLedgerEnvelopeSchema,
|
|
2603
|
-
event_type:
|
|
2604
|
-
stable_id:
|
|
2605
|
-
timestamp:
|
|
2606
|
-
reason:
|
|
2607
|
-
from_slug:
|
|
2608
|
-
to_slug:
|
|
2609
|
-
});
|
|
2610
|
-
var knowledgeDemotedEventSchema =
|
|
2814
|
+
event_type: z16.literal("knowledge_slug_renamed"),
|
|
2815
|
+
stable_id: z16.string().optional(),
|
|
2816
|
+
timestamp: z16.string().datetime(),
|
|
2817
|
+
reason: z16.string().optional(),
|
|
2818
|
+
from_slug: z16.string(),
|
|
2819
|
+
to_slug: z16.string()
|
|
2820
|
+
});
|
|
2821
|
+
var knowledgeDemotedEventSchema = z16.object({
|
|
2611
2822
|
...eventLedgerEnvelopeSchema,
|
|
2612
|
-
event_type:
|
|
2613
|
-
stable_id:
|
|
2614
|
-
timestamp:
|
|
2615
|
-
reason:
|
|
2823
|
+
event_type: z16.literal("knowledge_demoted"),
|
|
2824
|
+
stable_id: z16.string().optional(),
|
|
2825
|
+
timestamp: z16.string().datetime(),
|
|
2826
|
+
reason: z16.string().optional()
|
|
2616
2827
|
});
|
|
2617
|
-
var knowledgeArchivedEventSchema =
|
|
2828
|
+
var knowledgeArchivedEventSchema = z16.object({
|
|
2618
2829
|
...eventLedgerEnvelopeSchema,
|
|
2619
|
-
event_type:
|
|
2620
|
-
stable_id:
|
|
2621
|
-
timestamp:
|
|
2622
|
-
reason:
|
|
2830
|
+
event_type: z16.literal("knowledge_archived"),
|
|
2831
|
+
stable_id: z16.string().optional(),
|
|
2832
|
+
timestamp: z16.string().datetime(),
|
|
2833
|
+
reason: z16.string().optional()
|
|
2623
2834
|
});
|
|
2624
|
-
var knowledgeArchiveAttemptedEventSchema =
|
|
2835
|
+
var knowledgeArchiveAttemptedEventSchema = z16.object({
|
|
2625
2836
|
...eventLedgerEnvelopeSchema,
|
|
2626
|
-
event_type:
|
|
2627
|
-
stable_id:
|
|
2628
|
-
timestamp:
|
|
2629
|
-
reason:
|
|
2837
|
+
event_type: z16.literal("knowledge_archive_attempted"),
|
|
2838
|
+
stable_id: z16.string().optional(),
|
|
2839
|
+
timestamp: z16.string().datetime(),
|
|
2840
|
+
reason: z16.string().optional()
|
|
2630
2841
|
});
|
|
2631
|
-
var knowledgeUnarchivedEventSchema =
|
|
2842
|
+
var knowledgeUnarchivedEventSchema = z16.object({
|
|
2632
2843
|
...eventLedgerEnvelopeSchema,
|
|
2633
|
-
event_type:
|
|
2634
|
-
stable_id:
|
|
2635
|
-
timestamp:
|
|
2636
|
-
reason:
|
|
2844
|
+
event_type: z16.literal("knowledge_unarchived"),
|
|
2845
|
+
stable_id: z16.string().optional(),
|
|
2846
|
+
timestamp: z16.string().datetime(),
|
|
2847
|
+
reason: z16.string().optional(),
|
|
2637
2848
|
// 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:
|
|
2849
|
+
archive_path: z16.string().optional(),
|
|
2850
|
+
// Post-move canonical path (e.g. "knowledge/decisions/KT-DEC-0007--single-cjs-hook.md" inside the resolved store).
|
|
2851
|
+
restored_to: z16.string().optional()
|
|
2641
2852
|
});
|
|
2642
|
-
var knowledgeDeferredEventSchema =
|
|
2853
|
+
var knowledgeDeferredEventSchema = z16.object({
|
|
2643
2854
|
...eventLedgerEnvelopeSchema,
|
|
2644
|
-
event_type:
|
|
2645
|
-
stable_id:
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2855
|
+
event_type: z16.literal("knowledge_deferred"),
|
|
2856
|
+
stable_id: z16.string().optional(),
|
|
2857
|
+
pending_path: z16.string().optional(),
|
|
2858
|
+
timestamp: z16.string().datetime(),
|
|
2859
|
+
reason: z16.string().optional(),
|
|
2860
|
+
until: z16.string().datetime().optional()
|
|
2861
|
+
});
|
|
2862
|
+
var knowledgeRejectedEventSchema = z16.object({
|
|
2651
2863
|
...eventLedgerEnvelopeSchema,
|
|
2652
|
-
event_type:
|
|
2653
|
-
stable_id:
|
|
2654
|
-
timestamp:
|
|
2655
|
-
reason:
|
|
2864
|
+
event_type: z16.literal("knowledge_rejected"),
|
|
2865
|
+
stable_id: z16.string().optional(),
|
|
2866
|
+
timestamp: z16.string().datetime(),
|
|
2867
|
+
reason: z16.string()
|
|
2656
2868
|
});
|
|
2657
|
-
var knowledgeConsumedEventSchema =
|
|
2869
|
+
var knowledgeConsumedEventSchema = z16.object({
|
|
2658
2870
|
...eventLedgerEnvelopeSchema,
|
|
2659
|
-
event_type:
|
|
2660
|
-
stable_id:
|
|
2661
|
-
consumed_at:
|
|
2662
|
-
client_hash:
|
|
2871
|
+
event_type: z16.literal("knowledge_consumed"),
|
|
2872
|
+
stable_id: z16.string(),
|
|
2873
|
+
consumed_at: z16.string().datetime(),
|
|
2874
|
+
client_hash: z16.string()
|
|
2663
2875
|
});
|
|
2664
|
-
var knowledgeScopeDegradedEventSchema =
|
|
2876
|
+
var knowledgeScopeDegradedEventSchema = z16.object({
|
|
2665
2877
|
...eventLedgerEnvelopeSchema,
|
|
2666
|
-
event_type:
|
|
2667
|
-
stable_id:
|
|
2668
|
-
timestamp:
|
|
2669
|
-
from_scope:
|
|
2670
|
-
to_scope:
|
|
2671
|
-
reason:
|
|
2672
|
-
});
|
|
2673
|
-
var doctorRunEventSchema =
|
|
2878
|
+
event_type: z16.literal("knowledge_scope_degraded"),
|
|
2879
|
+
stable_id: z16.string(),
|
|
2880
|
+
timestamp: z16.string().datetime(),
|
|
2881
|
+
from_scope: z16.enum(["narrow", "broad"]),
|
|
2882
|
+
to_scope: z16.enum(["narrow", "broad"]),
|
|
2883
|
+
reason: z16.string()
|
|
2884
|
+
});
|
|
2885
|
+
var doctorRunEventSchema = z16.object({
|
|
2674
2886
|
...eventLedgerEnvelopeSchema,
|
|
2675
|
-
event_type:
|
|
2676
|
-
mode:
|
|
2677
|
-
issues:
|
|
2678
|
-
mutations:
|
|
2679
|
-
timestamp:
|
|
2887
|
+
event_type: z16.literal("doctor_run"),
|
|
2888
|
+
mode: z16.enum(["lint", "fix-knowledge"]),
|
|
2889
|
+
issues: z16.number().int().nonnegative(),
|
|
2890
|
+
mutations: z16.number().int().nonnegative().optional(),
|
|
2891
|
+
timestamp: z16.string().datetime()
|
|
2680
2892
|
});
|
|
2681
|
-
var knowledgePathDangledEventSchema =
|
|
2893
|
+
var knowledgePathDangledEventSchema = z16.object({
|
|
2682
2894
|
...eventLedgerEnvelopeSchema,
|
|
2683
|
-
event_type:
|
|
2684
|
-
stable_id:
|
|
2685
|
-
removed_glob:
|
|
2895
|
+
event_type: z16.literal("knowledge_path_dangled"),
|
|
2896
|
+
stable_id: z16.string(),
|
|
2897
|
+
removed_glob: z16.string()
|
|
2686
2898
|
});
|
|
2687
|
-
var relevanceMigrationRunEventSchema =
|
|
2899
|
+
var relevanceMigrationRunEventSchema = z16.object({
|
|
2688
2900
|
...eventLedgerEnvelopeSchema,
|
|
2689
|
-
event_type:
|
|
2690
|
-
timestamp:
|
|
2691
|
-
scanned_count:
|
|
2692
|
-
touched_count:
|
|
2901
|
+
event_type: z16.literal("relevance_migration_run"),
|
|
2902
|
+
timestamp: z16.string().datetime(),
|
|
2903
|
+
scanned_count: z16.number().int().nonnegative(),
|
|
2904
|
+
touched_count: z16.number().int().nonnegative()
|
|
2693
2905
|
});
|
|
2694
|
-
var pendingAutoArchivedEventSchema =
|
|
2906
|
+
var pendingAutoArchivedEventSchema = z16.object({
|
|
2695
2907
|
...eventLedgerEnvelopeSchema,
|
|
2696
|
-
event_type:
|
|
2697
|
-
pending_path:
|
|
2698
|
-
archived_to:
|
|
2699
|
-
reason:
|
|
2908
|
+
event_type: z16.literal("pending_auto_archived"),
|
|
2909
|
+
pending_path: z16.string(),
|
|
2910
|
+
archived_to: z16.string(),
|
|
2911
|
+
reason: z16.string()
|
|
2700
2912
|
});
|
|
2701
|
-
var assistantTurnObservedEventSchema =
|
|
2913
|
+
var assistantTurnObservedEventSchema = z16.object({
|
|
2702
2914
|
...eventLedgerEnvelopeSchema,
|
|
2703
|
-
event_type:
|
|
2704
|
-
kb_line_raw:
|
|
2705
|
-
cite_ids:
|
|
2706
|
-
cite_tags:
|
|
2915
|
+
event_type: z16.literal("assistant_turn_observed"),
|
|
2916
|
+
kb_line_raw: z16.string().nullable(),
|
|
2917
|
+
cite_ids: z16.array(z16.string()).default([]),
|
|
2918
|
+
cite_tags: z16.array(citeTagSchema).default([]),
|
|
2707
2919
|
// v2.0.0-rc.24 TASK-01: per-cite contract commitments. Index-aligned with
|
|
2708
2920
|
// cite_ids/cite_tags (commitments[i] belongs to cite_ids[i]). Each slot
|
|
2709
2921
|
// carries `operators[]` (kind + glob target) or `skip_reason` when the cite
|
|
@@ -2711,15 +2923,15 @@ var assistantTurnObservedEventSchema = z18.object({
|
|
|
2711
2923
|
// empty array via `.default([])` and are excluded from contract-policy
|
|
2712
2924
|
// audits by the marker-gate (see cite_contract_policy_activated below).
|
|
2713
2925
|
// Mirrors the rc.20 cite_tags parallel-array evolution exactly.
|
|
2714
|
-
cite_commitments:
|
|
2715
|
-
|
|
2716
|
-
operators:
|
|
2717
|
-
|
|
2718
|
-
kind:
|
|
2719
|
-
target:
|
|
2926
|
+
cite_commitments: z16.array(
|
|
2927
|
+
z16.object({
|
|
2928
|
+
operators: z16.array(
|
|
2929
|
+
z16.object({
|
|
2930
|
+
kind: z16.enum(["edit", "not_edit", "require", "forbid"]),
|
|
2931
|
+
target: z16.string()
|
|
2720
2932
|
})
|
|
2721
2933
|
),
|
|
2722
|
-
skip_reason:
|
|
2934
|
+
skip_reason: z16.string().nullable()
|
|
2723
2935
|
})
|
|
2724
2936
|
).default([]),
|
|
2725
2937
|
// lifecycle-refactor W3-T4 (§2 store 轴 / store-qualified 观测): per-cite store
|
|
@@ -2729,174 +2941,183 @@ var assistantTurnObservedEventSchema = z18.object({
|
|
|
2729
2941
|
// doctor --cite-coverage can break compliance down per store WITHOUT joining
|
|
2730
2942
|
// against the store registry. Additive `.optional()` (NOT `.default([])`) so
|
|
2731
2943
|
// 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 =
|
|
2944
|
+
// events parse with the field absent and bucket under the unqualified default.
|
|
2945
|
+
cite_stores: z16.array(z16.string().nullable()).optional(),
|
|
2946
|
+
client: z16.enum(["cc", "codex"]).optional(),
|
|
2947
|
+
turn_id: z16.string(),
|
|
2948
|
+
envelope_index: z16.number().int().nonnegative().optional(),
|
|
2949
|
+
timestamp: z16.string().datetime()
|
|
2950
|
+
});
|
|
2951
|
+
var citePolicyActivatedEventSchema = z16.object({
|
|
2740
2952
|
...eventLedgerEnvelopeSchema,
|
|
2741
|
-
event_type:
|
|
2742
|
-
policy_version:
|
|
2743
|
-
timestamp:
|
|
2953
|
+
event_type: z16.literal("cite_policy_activated"),
|
|
2954
|
+
policy_version: z16.string(),
|
|
2955
|
+
timestamp: z16.string().datetime()
|
|
2744
2956
|
});
|
|
2745
|
-
var citeContractPolicyActivatedEventSchema =
|
|
2957
|
+
var citeContractPolicyActivatedEventSchema = z16.object({
|
|
2746
2958
|
...eventLedgerEnvelopeSchema,
|
|
2747
|
-
event_type:
|
|
2959
|
+
event_type: z16.literal("cite_contract_policy_activated")
|
|
2748
2960
|
});
|
|
2749
|
-
var eventsRotatedEventSchema =
|
|
2961
|
+
var eventsRotatedEventSchema = z16.object({
|
|
2750
2962
|
...eventLedgerEnvelopeSchema,
|
|
2751
|
-
event_type:
|
|
2752
|
-
cutoff_ts:
|
|
2753
|
-
archived_count:
|
|
2754
|
-
kept_count:
|
|
2755
|
-
archive_path:
|
|
2963
|
+
event_type: z16.literal("events_rotated"),
|
|
2964
|
+
cutoff_ts: z16.string().datetime(),
|
|
2965
|
+
archived_count: z16.number().int().nonnegative(),
|
|
2966
|
+
kept_count: z16.number().int().nonnegative(),
|
|
2967
|
+
archive_path: z16.string()
|
|
2756
2968
|
});
|
|
2757
|
-
var knowledgeMetaAutoHealedEventSchema =
|
|
2969
|
+
var knowledgeMetaAutoHealedEventSchema = z16.object({
|
|
2758
2970
|
...eventLedgerEnvelopeSchema,
|
|
2759
|
-
event_type:
|
|
2760
|
-
previous_revision_hash:
|
|
2761
|
-
revision_hash:
|
|
2762
|
-
trigger:
|
|
2763
|
-
caller:
|
|
2971
|
+
event_type: z16.literal("knowledge_meta_auto_healed"),
|
|
2972
|
+
previous_revision_hash: z16.string(),
|
|
2973
|
+
revision_hash: z16.string(),
|
|
2974
|
+
trigger: z16.literal("read"),
|
|
2975
|
+
caller: z16.enum(["planContext", "getKnowledgeSections", "getKnowledge", "extractKnowledge"]).optional()
|
|
2764
2976
|
});
|
|
2765
|
-
var serveLockClearedEventSchema =
|
|
2977
|
+
var serveLockClearedEventSchema = z16.object({
|
|
2766
2978
|
...eventLedgerEnvelopeSchema,
|
|
2767
|
-
event_type:
|
|
2768
|
-
pid:
|
|
2769
|
-
age_ms:
|
|
2770
|
-
timestamp:
|
|
2979
|
+
event_type: z16.literal("serve_lock_cleared"),
|
|
2980
|
+
pid: z16.number().int().nonnegative(),
|
|
2981
|
+
age_ms: z16.number().int().nonnegative(),
|
|
2982
|
+
timestamp: z16.string().datetime()
|
|
2771
2983
|
});
|
|
2772
|
-
var knowledgeEnrichedEventSchema =
|
|
2984
|
+
var knowledgeEnrichedEventSchema = z16.object({
|
|
2773
2985
|
...eventLedgerEnvelopeSchema,
|
|
2774
|
-
event_type:
|
|
2775
|
-
path:
|
|
2776
|
-
added_fields:
|
|
2777
|
-
mode:
|
|
2778
|
-
timestamp:
|
|
2986
|
+
event_type: z16.literal("knowledge_enriched"),
|
|
2987
|
+
path: z16.string(),
|
|
2988
|
+
added_fields: z16.array(z16.enum(["intent_clues", "tech_stack", "impact", "must_read_if"])),
|
|
2989
|
+
mode: z16.enum(["auto", "preview", "readonly", "interactive"]),
|
|
2990
|
+
timestamp: z16.string().datetime()
|
|
2779
2991
|
});
|
|
2780
|
-
var sessionArchiveAttemptedEventSchema =
|
|
2992
|
+
var sessionArchiveAttemptedEventSchema = z16.object({
|
|
2781
2993
|
...eventLedgerEnvelopeSchema,
|
|
2782
|
-
event_type:
|
|
2783
|
-
outcome:
|
|
2784
|
-
covered_through_ts:
|
|
2785
|
-
candidates_proposed:
|
|
2786
|
-
knowledge_proposed_ids:
|
|
2994
|
+
event_type: z16.literal("session_archive_attempted"),
|
|
2995
|
+
outcome: z16.enum(["proposed", "viability_failed", "user_dismissed", "skipped_no_signal"]),
|
|
2996
|
+
covered_through_ts: z16.number().int().nonnegative(),
|
|
2997
|
+
candidates_proposed: z16.number().int().nonnegative().default(0),
|
|
2998
|
+
knowledge_proposed_ids: z16.array(z16.string()).default([])
|
|
2787
2999
|
});
|
|
2788
|
-
var hookSurfaceEmittedEventSchema =
|
|
3000
|
+
var hookSurfaceEmittedEventSchema = z16.object({
|
|
2789
3001
|
...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 =
|
|
3002
|
+
event_type: z16.literal("hook_surface_emitted"),
|
|
3003
|
+
hook_name: z16.string(),
|
|
3004
|
+
client: z16.enum(["cc", "codex"]),
|
|
3005
|
+
target_channel: z16.string(),
|
|
3006
|
+
rendered_ids: z16.array(z16.string()),
|
|
3007
|
+
delivery_status: z16.enum(["delivered", "suppressed", "error"]),
|
|
3008
|
+
suppression_reason: z16.string().optional()
|
|
3009
|
+
});
|
|
3010
|
+
var hookSignalEmittedEventSchema = z16.object({
|
|
2799
3011
|
...eventLedgerEnvelopeSchema,
|
|
2800
|
-
event_type:
|
|
2801
|
-
signal_type:
|
|
2802
|
-
threshold:
|
|
2803
|
-
actual_value:
|
|
2804
|
-
fired:
|
|
3012
|
+
event_type: z16.literal("hook_signal_emitted"),
|
|
3013
|
+
signal_type: z16.enum(["archive", "review", "maintenance", "other"]),
|
|
3014
|
+
threshold: z16.number(),
|
|
3015
|
+
actual_value: z16.number(),
|
|
3016
|
+
fired: z16.boolean()
|
|
2805
3017
|
});
|
|
2806
|
-
var mcpStdioTraceEventSchema =
|
|
3018
|
+
var mcpStdioTraceEventSchema = z16.object({
|
|
2807
3019
|
...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 =
|
|
3020
|
+
event_type: z16.literal("mcp_stdio_trace"),
|
|
3021
|
+
tool_name: z16.string(),
|
|
3022
|
+
request_id: z16.string(),
|
|
3023
|
+
duration_ms: z16.number().nonnegative(),
|
|
3024
|
+
status: z16.enum(["ok", "error"]),
|
|
3025
|
+
payload_bytes_in: z16.number().int().nonnegative(),
|
|
3026
|
+
payload_bytes_out: z16.number().int().nonnegative(),
|
|
3027
|
+
error_code: z16.string().optional()
|
|
3028
|
+
});
|
|
3029
|
+
var payloadGuardObservedEventSchema = z16.object({
|
|
2818
3030
|
...eventLedgerEnvelopeSchema,
|
|
2819
|
-
event_type:
|
|
2820
|
-
tool_name:
|
|
2821
|
-
path_count:
|
|
2822
|
-
tokens_estimated:
|
|
2823
|
-
truncated:
|
|
2824
|
-
cap:
|
|
2825
|
-
});
|
|
2826
|
-
var skillInvocationStartedEventSchema =
|
|
3031
|
+
event_type: z16.literal("payload_guard_observed"),
|
|
3032
|
+
tool_name: z16.string(),
|
|
3033
|
+
path_count: z16.number().int().nonnegative(),
|
|
3034
|
+
tokens_estimated: z16.number().int().nonnegative(),
|
|
3035
|
+
truncated: z16.boolean(),
|
|
3036
|
+
cap: z16.number().int().positive()
|
|
3037
|
+
});
|
|
3038
|
+
var skillInvocationStartedEventSchema = z16.object({
|
|
2827
3039
|
...eventLedgerEnvelopeSchema,
|
|
2828
|
-
event_type:
|
|
2829
|
-
skill_name:
|
|
2830
|
-
trigger_source:
|
|
2831
|
-
entry_point:
|
|
3040
|
+
event_type: z16.literal("skill_invocation_started"),
|
|
3041
|
+
skill_name: z16.string(),
|
|
3042
|
+
trigger_source: z16.enum(["user", "auto_invoke", "ai_self_trigger", "chained"]),
|
|
3043
|
+
entry_point: z16.string()
|
|
2832
3044
|
});
|
|
2833
|
-
var skillInvocationCompletedEventSchema =
|
|
3045
|
+
var skillInvocationCompletedEventSchema = z16.object({
|
|
2834
3046
|
...eventLedgerEnvelopeSchema,
|
|
2835
|
-
event_type:
|
|
2836
|
-
skill_name:
|
|
2837
|
-
trigger_source:
|
|
2838
|
-
entry_point:
|
|
2839
|
-
outcome:
|
|
2840
|
-
elapsed_ms:
|
|
2841
|
-
});
|
|
2842
|
-
var skillPhaseTransitionEventSchema =
|
|
3047
|
+
event_type: z16.literal("skill_invocation_completed"),
|
|
3048
|
+
skill_name: z16.string(),
|
|
3049
|
+
trigger_source: z16.enum(["user", "auto_invoke", "ai_self_trigger", "chained"]),
|
|
3050
|
+
entry_point: z16.string(),
|
|
3051
|
+
outcome: z16.enum(["completed", "aborted", "error", "no_op"]),
|
|
3052
|
+
elapsed_ms: z16.number().nonnegative().optional()
|
|
3053
|
+
});
|
|
3054
|
+
var skillPhaseTransitionEventSchema = z16.object({
|
|
2843
3055
|
...eventLedgerEnvelopeSchema,
|
|
2844
|
-
event_type:
|
|
2845
|
-
skill_name:
|
|
2846
|
-
phase:
|
|
2847
|
-
status:
|
|
2848
|
-
checkpoint:
|
|
2849
|
-
elapsed_ms:
|
|
2850
|
-
});
|
|
2851
|
-
var skillTriggerCandidateEventSchema =
|
|
3056
|
+
event_type: z16.literal("skill_phase_transition"),
|
|
3057
|
+
skill_name: z16.string(),
|
|
3058
|
+
phase: z16.string(),
|
|
3059
|
+
status: z16.enum(["entered", "completed", "skipped", "failed"]),
|
|
3060
|
+
checkpoint: z16.string().optional(),
|
|
3061
|
+
elapsed_ms: z16.number().nonnegative().optional()
|
|
3062
|
+
});
|
|
3063
|
+
var skillTriggerCandidateEventSchema = z16.object({
|
|
2852
3064
|
...eventLedgerEnvelopeSchema,
|
|
2853
|
-
event_type:
|
|
2854
|
-
skill_name:
|
|
2855
|
-
trigger_source:
|
|
2856
|
-
signal:
|
|
2857
|
-
invoked:
|
|
3065
|
+
event_type: z16.literal("skill_trigger_candidate"),
|
|
3066
|
+
skill_name: z16.string(),
|
|
3067
|
+
trigger_source: z16.enum(["user", "auto_invoke", "ai_self_trigger", "chained"]),
|
|
3068
|
+
signal: z16.string(),
|
|
3069
|
+
invoked: z16.boolean()
|
|
2858
3070
|
});
|
|
2859
|
-
var llmJudgeRunEventSchema =
|
|
3071
|
+
var llmJudgeRunEventSchema = z16.object({
|
|
2860
3072
|
...eventLedgerEnvelopeSchema,
|
|
2861
|
-
event_type:
|
|
2862
|
-
prompt:
|
|
2863
|
-
version:
|
|
2864
|
-
model:
|
|
2865
|
-
input_trace_id:
|
|
2866
|
-
score:
|
|
2867
|
-
rationale:
|
|
2868
|
-
});
|
|
2869
|
-
var clientCapabilitySnapshotEventSchema =
|
|
3073
|
+
event_type: z16.literal("llm_judge_run"),
|
|
3074
|
+
prompt: z16.string(),
|
|
3075
|
+
version: z16.string(),
|
|
3076
|
+
model: z16.string(),
|
|
3077
|
+
input_trace_id: z16.string(),
|
|
3078
|
+
score: z16.number(),
|
|
3079
|
+
rationale: z16.string()
|
|
3080
|
+
});
|
|
3081
|
+
var clientCapabilitySnapshotEventSchema = z16.object({
|
|
2870
3082
|
...eventLedgerEnvelopeSchema,
|
|
2871
|
-
event_type:
|
|
2872
|
-
client:
|
|
2873
|
-
capabilities:
|
|
2874
|
-
version:
|
|
3083
|
+
event_type: z16.literal("client_capability_snapshot"),
|
|
3084
|
+
client: z16.enum(["cc", "codex"]),
|
|
3085
|
+
capabilities: z16.array(z16.string()),
|
|
3086
|
+
version: z16.string()
|
|
2875
3087
|
});
|
|
2876
|
-
var sessionEndedEventSchema =
|
|
3088
|
+
var sessionEndedEventSchema = z16.object({
|
|
2877
3089
|
...eventLedgerEnvelopeSchema,
|
|
2878
|
-
event_type:
|
|
3090
|
+
event_type: z16.literal("session_ended")
|
|
2879
3091
|
});
|
|
2880
|
-
var fileMutatedEventSchema =
|
|
3092
|
+
var fileMutatedEventSchema = z16.object({
|
|
2881
3093
|
...eventLedgerEnvelopeSchema,
|
|
2882
|
-
event_type:
|
|
2883
|
-
path:
|
|
2884
|
-
tool_call_id:
|
|
2885
|
-
tool_name:
|
|
2886
|
-
source_event_id:
|
|
2887
|
-
store_id:
|
|
2888
|
-
});
|
|
2889
|
-
var
|
|
3094
|
+
event_type: z16.literal("file_mutated"),
|
|
3095
|
+
path: z16.string(),
|
|
3096
|
+
tool_call_id: z16.string(),
|
|
3097
|
+
tool_name: z16.string().optional(),
|
|
3098
|
+
source_event_id: z16.string().optional(),
|
|
3099
|
+
store_id: z16.string().optional()
|
|
3100
|
+
});
|
|
3101
|
+
var knowledgeBodyReadEventSchema = z16.object({
|
|
2890
3102
|
...eventLedgerEnvelopeSchema,
|
|
2891
|
-
event_type:
|
|
3103
|
+
event_type: z16.literal("knowledge_body_read"),
|
|
3104
|
+
stable_id: z16.string(),
|
|
3105
|
+
store: z16.string().optional(),
|
|
3106
|
+
path: z16.string(),
|
|
3107
|
+
tool_call_id: z16.string().optional(),
|
|
3108
|
+
tool_name: z16.string().optional()
|
|
3109
|
+
});
|
|
3110
|
+
var precompactObservedEventSchema = z16.object({
|
|
3111
|
+
...eventLedgerEnvelopeSchema,
|
|
3112
|
+
event_type: z16.literal("precompact_observed")
|
|
2892
3113
|
});
|
|
2893
|
-
var graphEdgeCandidateRequestedEventSchema =
|
|
3114
|
+
var graphEdgeCandidateRequestedEventSchema = z16.object({
|
|
2894
3115
|
...eventLedgerEnvelopeSchema,
|
|
2895
|
-
event_type:
|
|
2896
|
-
stable_id:
|
|
2897
|
-
store:
|
|
3116
|
+
event_type: z16.literal("graph_edge_candidate_requested"),
|
|
3117
|
+
stable_id: z16.string(),
|
|
3118
|
+
store: z16.string().optional()
|
|
2898
3119
|
});
|
|
2899
|
-
var eventLedgerEventSchema =
|
|
3120
|
+
var eventLedgerEventSchema = z16.discriminatedUnion("event_type", [
|
|
2900
3121
|
knowledgeContextPlannedEventSchema,
|
|
2901
3122
|
knowledgeSelectionEventSchema,
|
|
2902
3123
|
knowledgeSectionsFetchedEventSchema,
|
|
@@ -2906,10 +3127,6 @@ var eventLedgerEventSchema = z18.discriminatedUnion("event_type", [
|
|
|
2906
3127
|
reapplyCompletedEventSchema,
|
|
2907
3128
|
installDiffAppliedEventSchema,
|
|
2908
3129
|
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
3130
|
metaReconciledOnStartupEventSchema,
|
|
2914
3131
|
metaReconciledEventSchema,
|
|
2915
3132
|
claudeSkillPathMigratedEventSchema,
|
|
@@ -2921,6 +3138,7 @@ var eventLedgerEventSchema = z18.discriminatedUnion("event_type", [
|
|
|
2921
3138
|
knowledgePromoteStartedEventSchema,
|
|
2922
3139
|
knowledgePromotedEventSchema,
|
|
2923
3140
|
knowledgePromoteFailedEventSchema,
|
|
3141
|
+
knowledgeModifiedEventSchema,
|
|
2924
3142
|
knowledgeLayerChangedEventSchema,
|
|
2925
3143
|
// v2.0.0-rc.37 NEW-24: dedicated old→new stable_id mapping event
|
|
2926
3144
|
knowledgeIdRedirectEventSchema,
|
|
@@ -2992,6 +3210,9 @@ var eventLedgerEventSchema = z18.discriminatedUnion("event_type", [
|
|
|
2992
3210
|
// lifecycle-refactor Wave 2 — dormant-hook activation markers.
|
|
2993
3211
|
sessionEndedEventSchema,
|
|
2994
3212
|
fileMutatedEventSchema,
|
|
3213
|
+
// KT-DEC-0030: knowledge_body_read — PostToolUse native-Read consumption marker
|
|
3214
|
+
// (replaces knowledge_consumed as the funnel's "body opened" signal).
|
|
3215
|
+
knowledgeBodyReadEventSchema,
|
|
2995
3216
|
precompactObservedEventSchema,
|
|
2996
3217
|
graphEdgeCandidateRequestedEventSchema
|
|
2997
3218
|
]);
|
|
@@ -3024,51 +3245,16 @@ function tokenize(text) {
|
|
|
3024
3245
|
}
|
|
3025
3246
|
return tokens;
|
|
3026
3247
|
}
|
|
3027
|
-
|
|
3028
|
-
// src/retrieval-budget.ts
|
|
3029
|
-
var PROFILES = {
|
|
3030
|
-
conservative: {
|
|
3031
|
-
topK: 12,
|
|
3032
|
-
payloadWarnBytes: 8192,
|
|
3033
|
-
payloadHardBytes: 32768,
|
|
3034
|
-
injectionChars: 1e3
|
|
3035
|
-
},
|
|
3036
|
-
balanced: {
|
|
3037
|
-
topK: 24,
|
|
3038
|
-
payloadWarnBytes: 16384,
|
|
3039
|
-
payloadHardBytes: 65536,
|
|
3040
|
-
injectionChars: 2e3
|
|
3041
|
-
},
|
|
3042
|
-
generous: {
|
|
3043
|
-
topK: 48,
|
|
3044
|
-
payloadWarnBytes: 32768,
|
|
3045
|
-
payloadHardBytes: 131072,
|
|
3046
|
-
injectionChars: 4e3
|
|
3047
|
-
}
|
|
3048
|
-
};
|
|
3049
|
-
var DEFAULT_RETRIEVAL_BUDGET_PROFILE = "balanced";
|
|
3050
|
-
function resolveRetrievalBudget(overrides) {
|
|
3051
|
-
const base = PROFILES[overrides?.profile ?? DEFAULT_RETRIEVAL_BUDGET_PROFILE];
|
|
3052
|
-
return {
|
|
3053
|
-
topK: overrides?.topK ?? base.topK,
|
|
3054
|
-
payloadWarnBytes: overrides?.payloadWarnBytes ?? base.payloadWarnBytes,
|
|
3055
|
-
payloadHardBytes: overrides?.payloadHardBytes ?? base.payloadHardBytes,
|
|
3056
|
-
injectionChars: overrides?.injectionChars ?? base.injectionChars
|
|
3057
|
-
};
|
|
3058
|
-
}
|
|
3059
|
-
function retrievalBudgetProfile(profile) {
|
|
3060
|
-
return PROFILES[profile];
|
|
3061
|
-
}
|
|
3062
3248
|
export {
|
|
3063
3249
|
AGENTS_META_IDENTITY_SOURCES,
|
|
3064
|
-
AGENTS_META_LAYERS,
|
|
3065
3250
|
AGENTS_META_TOPOLOGY_TYPES,
|
|
3066
3251
|
AgentsMetaCountersSchema,
|
|
3067
|
-
|
|
3252
|
+
BOOTSTRAP_CANONICAL_BY_LOCALE,
|
|
3253
|
+
BOOTSTRAP_CANONICAL_EN,
|
|
3254
|
+
BOOTSTRAP_CANONICAL_ZH,
|
|
3068
3255
|
BOOTSTRAP_MARKER_BEGIN,
|
|
3069
3256
|
BOOTSTRAP_MARKER_END,
|
|
3070
3257
|
BOOTSTRAP_REGEX,
|
|
3071
|
-
DEFAULT_RETRIEVAL_BUDGET_PROFILE,
|
|
3072
3258
|
FabExtractKnowledgeInputSchema,
|
|
3073
3259
|
FabExtractKnowledgeInputShape,
|
|
3074
3260
|
FabExtractKnowledgeOutputSchema,
|
|
@@ -3084,9 +3270,6 @@ export {
|
|
|
3084
3270
|
KNOWN_SCOPE_PREFIXES,
|
|
3085
3271
|
KnowledgeEntryFrontmatterSchema,
|
|
3086
3272
|
KnowledgeTypeSchema,
|
|
3087
|
-
LEGACY_KB_MARKER_BEGIN,
|
|
3088
|
-
LEGACY_KB_MARKER_END,
|
|
3089
|
-
LEGACY_KB_REGEX,
|
|
3090
3273
|
LayerSchema,
|
|
3091
3274
|
MCP_STORE_AWARE_CONTRACTS,
|
|
3092
3275
|
MCP_STORE_AWARE_TOOLS,
|
|
@@ -3098,16 +3281,18 @@ export {
|
|
|
3098
3281
|
PERSONAL_SCOPE,
|
|
3099
3282
|
PERSONAL_STORE_SENTINEL,
|
|
3100
3283
|
PROJECT_ROOT_SIGNALS,
|
|
3101
|
-
|
|
3284
|
+
PROPOSED_REASON_DESCRIPTIONS_BY_LOCALE,
|
|
3102
3285
|
PROTECTED_TOKENS,
|
|
3103
3286
|
ProposedReasonSchema,
|
|
3104
3287
|
REDACTION_PLACEHOLDER_PREFIX,
|
|
3105
|
-
ResolverNotImplementedError,
|
|
3106
3288
|
SCOPE_COORDINATE_PATTERN,
|
|
3107
3289
|
STORES_ROOT_DIR,
|
|
3290
|
+
STORE_ALIAS_PATTERN,
|
|
3108
3291
|
STORE_GITIGNORE,
|
|
3109
3292
|
STORE_KNOWLEDGE_TYPE_DIRS,
|
|
3110
3293
|
STORE_LAYOUT,
|
|
3294
|
+
STORE_MOUNT_GROUPS,
|
|
3295
|
+
STORE_MOUNT_NAME_PATTERN,
|
|
3111
3296
|
STORE_PENDING_DIR,
|
|
3112
3297
|
STORE_PROJECT_ID_PATTERN,
|
|
3113
3298
|
STORE_RESOLVER_WARNING_CODES,
|
|
@@ -3117,7 +3302,6 @@ export {
|
|
|
3117
3302
|
addMountedStore,
|
|
3118
3303
|
addStoreProject,
|
|
3119
3304
|
agentsIdentitySourceSchema,
|
|
3120
|
-
agentsLayerSchema,
|
|
3121
3305
|
agentsMetaNodeSchema,
|
|
3122
3306
|
agentsMetaSchema,
|
|
3123
3307
|
agentsTopologyTypeSchema,
|
|
@@ -3133,7 +3317,6 @@ export {
|
|
|
3133
3317
|
auditModeSchema,
|
|
3134
3318
|
bindRequiredStore,
|
|
3135
3319
|
bindingsSnapshotPath,
|
|
3136
|
-
bootstrapMarkerMigratedEventSchema,
|
|
3137
3320
|
buildDebugBundle,
|
|
3138
3321
|
buildFailureTrace,
|
|
3139
3322
|
buildScanRecommendations,
|
|
@@ -3156,11 +3339,12 @@ export {
|
|
|
3156
3339
|
defaultLayerFilterSchema,
|
|
3157
3340
|
defaultMessages,
|
|
3158
3341
|
deriveAgentsMetaIdentitySource,
|
|
3159
|
-
deriveAgentsMetaLayer,
|
|
3160
3342
|
deriveAgentsMetaStableId,
|
|
3161
3343
|
deriveAgentsMetaTopologyType,
|
|
3344
|
+
deriveMountLabel,
|
|
3162
3345
|
detachMountedStore,
|
|
3163
3346
|
detectNodeLocale,
|
|
3347
|
+
disambiguateAlias,
|
|
3164
3348
|
doctorRunEventSchema,
|
|
3165
3349
|
driftDetectedEventSchema,
|
|
3166
3350
|
editIntentCheckedEventSchema,
|
|
@@ -3220,6 +3404,7 @@ export {
|
|
|
3220
3404
|
isPersonalScope,
|
|
3221
3405
|
knowledgeArchiveAttemptedEventSchema,
|
|
3222
3406
|
knowledgeArchivedEventSchema,
|
|
3407
|
+
knowledgeBodyReadEventSchema,
|
|
3223
3408
|
knowledgeConsumedEventSchema,
|
|
3224
3409
|
knowledgeContextPlannedEventSchema,
|
|
3225
3410
|
knowledgeDeferredEventSchema,
|
|
@@ -3229,6 +3414,7 @@ export {
|
|
|
3229
3414
|
knowledgeIdRedirectEventSchema,
|
|
3230
3415
|
knowledgeLayerChangedEventSchema,
|
|
3231
3416
|
knowledgeMetaAutoHealedEventSchema,
|
|
3417
|
+
knowledgeModifiedEventSchema,
|
|
3232
3418
|
knowledgePathDangledEventSchema,
|
|
3233
3419
|
knowledgePromoteFailedEventSchema,
|
|
3234
3420
|
knowledgePromoteStartedEventSchema,
|
|
@@ -3259,7 +3445,7 @@ export {
|
|
|
3259
3445
|
localKnowledgeIdSchema,
|
|
3260
3446
|
lockApprovedEventSchema,
|
|
3261
3447
|
lockDriftEventSchema,
|
|
3262
|
-
|
|
3448
|
+
matchBootstrapCanonicalLocale,
|
|
3263
3449
|
mcpEventLedgerEventSchema,
|
|
3264
3450
|
mcpPayloadLimitsSchema,
|
|
3265
3451
|
mcpStdioTraceEventSchema,
|
|
@@ -3269,6 +3455,8 @@ export {
|
|
|
3269
3455
|
mountedStoreSchema,
|
|
3270
3456
|
normalizeCiteTag,
|
|
3271
3457
|
normalizeLocale,
|
|
3458
|
+
nudgeModeSchema,
|
|
3459
|
+
observeConfigSchema,
|
|
3272
3460
|
onboardSlotSchema,
|
|
3273
3461
|
parityCapabilitySchema,
|
|
3274
3462
|
parityClientExpectationSchema,
|
|
@@ -3300,6 +3488,7 @@ export {
|
|
|
3300
3488
|
readSetGoldenFileSchema,
|
|
3301
3489
|
readStoreCounters,
|
|
3302
3490
|
readStoreIdentity,
|
|
3491
|
+
readStoreIdentityAsync,
|
|
3303
3492
|
readStoreProjects,
|
|
3304
3493
|
reapplyCompletedEventSchema,
|
|
3305
3494
|
recallAnnotations,
|
|
@@ -3307,16 +3496,18 @@ export {
|
|
|
3307
3496
|
recallOutputSchema,
|
|
3308
3497
|
recognizeStoreDir,
|
|
3309
3498
|
reconcileStoreCounters,
|
|
3499
|
+
redactPii,
|
|
3310
3500
|
redactSecrets,
|
|
3311
3501
|
relevanceMigrationRunEventSchema,
|
|
3312
3502
|
requiredStoreEntrySchema,
|
|
3503
|
+
resolveBootstrapCanonical,
|
|
3313
3504
|
resolveCandidates,
|
|
3314
3505
|
resolveFabricLocale,
|
|
3506
|
+
resolveGlobalLocale,
|
|
3315
3507
|
resolveGlobalRoot,
|
|
3316
|
-
resolveRetrievalBudget,
|
|
3317
3508
|
resolveStoreQualifiedId,
|
|
3509
|
+
resolveWorkspaceBindingId,
|
|
3318
3510
|
resolvedBindingsSnapshotSchema,
|
|
3319
|
-
retrievalBudgetProfile,
|
|
3320
3511
|
ruleDescriptionIndexItemSchema,
|
|
3321
3512
|
ruleDescriptionSchema,
|
|
3322
3513
|
saveGlobalConfig,
|
|
@@ -3333,16 +3524,21 @@ export {
|
|
|
3333
3524
|
skillInvocationStartedEventSchema,
|
|
3334
3525
|
skillPhaseTransitionEventSchema,
|
|
3335
3526
|
skillTriggerCandidateEventSchema,
|
|
3527
|
+
storeAliasSchema,
|
|
3336
3528
|
storeAwareEntrySchema,
|
|
3337
3529
|
storeCountersPath,
|
|
3338
3530
|
storeCountersSchema,
|
|
3339
3531
|
storeHasProject,
|
|
3340
3532
|
storeIdentitySchema,
|
|
3341
3533
|
storeKnowledgeTypeDir,
|
|
3534
|
+
storeMountGroup,
|
|
3535
|
+
storeMountNameSchema,
|
|
3536
|
+
storeMountSubPath,
|
|
3342
3537
|
storeProjectSchema,
|
|
3343
3538
|
storeProjectsFileSchema,
|
|
3344
3539
|
storeReadSetSchema,
|
|
3345
3540
|
storeRelativePath,
|
|
3541
|
+
storeRelativePathForMount,
|
|
3346
3542
|
storeResolveInputSchema,
|
|
3347
3543
|
storeResolverWarningCodeSchema,
|
|
3348
3544
|
storeResolverWarningSchema,
|
|
@@ -3352,6 +3548,7 @@ export {
|
|
|
3352
3548
|
uidSchema,
|
|
3353
3549
|
withDerivedAgentsMetaNodeDefaults,
|
|
3354
3550
|
writeBindingsSnapshot,
|
|
3551
|
+
writeRouteSchema,
|
|
3355
3552
|
writeTargetSchema,
|
|
3356
3553
|
writtenToStoreSchema,
|
|
3357
3554
|
zhCNMessages
|