@fenglimg/fabric-shared 2.0.0 → 2.1.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +13 -0
- package/dist/chunk-MDWTGOAY.js +101 -0
- package/dist/chunk-R2J7DAED.js +2043 -0
- package/dist/chunk-WVPDH4BF.js +952 -0
- package/dist/i18n/index.d.ts +22 -2
- package/dist/i18n/index.js +3 -1
- package/dist/index-GQpaWTm-.d.ts +328 -0
- package/dist/index.d.ts +4922 -1998
- package/dist/index.js +2114 -372
- package/dist/node/atomic-write.d.ts +16 -0
- package/dist/node/atomic-write.js +19 -10
- package/dist/node/mcp-payload-guard.d.ts +3 -1
- package/dist/node/mcp-payload-guard.js +6 -2
- package/dist/schemas/api-contracts.d.ts +1562 -815
- package/dist/schemas/api-contracts.js +23 -7
- package/dist/templates/bootstrap-canonical.d.ts +56 -0
- package/dist/templates/bootstrap-canonical.js +18 -0
- package/dist/types/index.d.ts +2 -123
- package/package.json +32 -4
- package/dist/chunk-U2SR2M4L.js +0 -958
- package/dist/chunk-VQDCDCJA.js +0 -555
package/dist/index.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BOOTSTRAP_CANONICAL,
|
|
3
|
+
BOOTSTRAP_MARKER_BEGIN,
|
|
4
|
+
BOOTSTRAP_MARKER_END,
|
|
5
|
+
BOOTSTRAP_REGEX,
|
|
6
|
+
LEGACY_KB_MARKER_BEGIN,
|
|
7
|
+
LEGACY_KB_MARKER_END,
|
|
8
|
+
LEGACY_KB_REGEX
|
|
9
|
+
} from "./chunk-MDWTGOAY.js";
|
|
1
10
|
import {
|
|
2
11
|
PROTECTED_TOKENS,
|
|
3
12
|
createTranslator,
|
|
@@ -5,29 +14,37 @@ import {
|
|
|
5
14
|
detectNodeLocale,
|
|
6
15
|
enMessages,
|
|
7
16
|
normalizeLocale,
|
|
17
|
+
resolveFabricLocale,
|
|
8
18
|
zhCNMessages
|
|
9
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-R2J7DAED.js";
|
|
10
20
|
import {
|
|
11
21
|
FabExtractKnowledgeInputSchema,
|
|
12
22
|
FabExtractKnowledgeInputShape,
|
|
13
23
|
FabExtractKnowledgeOutputSchema,
|
|
14
24
|
FabReviewInputSchema,
|
|
25
|
+
FabReviewInputShape,
|
|
15
26
|
FabReviewOutputSchema,
|
|
27
|
+
FabReviewOutputShape,
|
|
16
28
|
KNOWLEDGE_TYPE_CODES,
|
|
17
29
|
KnowledgeEntryFrontmatterSchema,
|
|
18
30
|
KnowledgeTypeSchema,
|
|
19
31
|
LayerSchema,
|
|
20
32
|
MaturitySchema,
|
|
33
|
+
ONBOARD_SLOT_NAMES,
|
|
34
|
+
ONBOARD_SLOT_TOTAL,
|
|
21
35
|
PROPOSED_REASON_DESCRIPTIONS,
|
|
22
36
|
ProposedReasonSchema,
|
|
23
37
|
StableIdSchema,
|
|
24
38
|
annotateIntentRequestSchema,
|
|
39
|
+
archiveScanAnnotations,
|
|
40
|
+
archiveScanInputSchema,
|
|
41
|
+
archiveScanOutputSchema,
|
|
42
|
+
citeContractMetricsSchema,
|
|
43
|
+
citeCoverageReportSchema,
|
|
44
|
+
citeLayerTypeBreakdownSchema,
|
|
25
45
|
fabExtractKnowledgeAnnotations,
|
|
26
46
|
fabReviewAnnotations,
|
|
27
47
|
formatKnowledgeId,
|
|
28
|
-
getKnowledgeAnnotations,
|
|
29
|
-
getKnowledgeInputSchema,
|
|
30
|
-
getKnowledgeOutputSchema,
|
|
31
48
|
historyStateQuerySchema,
|
|
32
49
|
humanLockApproveRequestSchema,
|
|
33
50
|
humanLockFileParamsSchema,
|
|
@@ -36,19 +53,30 @@ import {
|
|
|
36
53
|
knowledgeSectionsOutputSchema,
|
|
37
54
|
ledgerQuerySchema,
|
|
38
55
|
ledgerSourceSchema,
|
|
56
|
+
onboardSlotSchema,
|
|
39
57
|
parseKnowledgeId,
|
|
40
58
|
planContextAnnotations,
|
|
41
59
|
planContextHintNarrowEntrySchema,
|
|
42
60
|
planContextHintOutputSchema,
|
|
43
61
|
planContextInputSchema,
|
|
44
62
|
planContextOutputSchema,
|
|
63
|
+
recallAnnotations,
|
|
64
|
+
recallInputSchema,
|
|
65
|
+
recallOutputSchema,
|
|
45
66
|
structuredWarningSchema
|
|
46
|
-
} from "./chunk-
|
|
67
|
+
} from "./chunk-WVPDH4BF.js";
|
|
47
68
|
import "./chunk-LXNCAKJZ.js";
|
|
48
69
|
|
|
49
70
|
// src/schemas/agents-meta.ts
|
|
50
71
|
import { z } from "zod";
|
|
51
72
|
var FABRIC_AGENTS_PREFIX = ".fabric/agents/";
|
|
73
|
+
var KNOWLEDGE_TYPE_SINGULAR_TO_PLURAL = {
|
|
74
|
+
model: "models",
|
|
75
|
+
decision: "decisions",
|
|
76
|
+
guideline: "guidelines",
|
|
77
|
+
pitfall: "pitfalls",
|
|
78
|
+
process: "processes"
|
|
79
|
+
};
|
|
52
80
|
var AGENTS_META_LAYERS = ["L0", "L1", "L2"];
|
|
53
81
|
var AGENTS_META_TOPOLOGY_TYPES = ["mirror", "cross-cutting", "domain", "local", "global"];
|
|
54
82
|
var AGENTS_META_IDENTITY_SOURCES = ["declared", "derived"];
|
|
@@ -64,7 +92,15 @@ var ruleDescriptionSchema = z.object({
|
|
|
64
92
|
entities: z.array(z.string()).optional(),
|
|
65
93
|
// v2.0 knowledge entry fields (TASK-002 schemas). All optional for backward compat.
|
|
66
94
|
id: z.string().optional(),
|
|
67
|
-
|
|
95
|
+
// rc.31 NEW-1: forward-compat for legacy on-disk agents.meta.json carrying
|
|
96
|
+
// singular knowledge_type values (model/decision/guideline/pitfall/process).
|
|
97
|
+
// Normalize to canonical plural form before enum validation so doctor and
|
|
98
|
+
// plan-context-hint can load pre-rc.28 meta files without aborting. Disk
|
|
99
|
+
// gets rewritten to plural on next reconcile (via knowledge-meta-builder).
|
|
100
|
+
knowledge_type: z.preprocess(
|
|
101
|
+
(value) => typeof value === "string" && value in KNOWLEDGE_TYPE_SINGULAR_TO_PLURAL ? KNOWLEDGE_TYPE_SINGULAR_TO_PLURAL[value] : value,
|
|
102
|
+
z.enum(["models", "decisions", "guidelines", "pitfalls", "processes"])
|
|
103
|
+
).optional(),
|
|
68
104
|
maturity: z.enum(["draft", "verified", "proven"]).optional(),
|
|
69
105
|
knowledge_layer: z.enum(["personal", "team"]).optional(),
|
|
70
106
|
layer_reason: z.string().optional(),
|
|
@@ -134,8 +170,7 @@ function withDerivedAgentsMetaNodeDefaults(node) {
|
|
|
134
170
|
const identitySource = isKnowledgeEntry ? "declared" : deriveAgentsMetaIdentitySource(node);
|
|
135
171
|
return {
|
|
136
172
|
...node,
|
|
137
|
-
|
|
138
|
-
level: node.level ?? node.layer ?? deriveAgentsMetaLayer(node.file),
|
|
173
|
+
level: node.level ?? deriveAgentsMetaLayer(node.file),
|
|
139
174
|
topology_type: node.topology_type ?? deriveAgentsMetaTopologyType(node.file),
|
|
140
175
|
stable_id: stableId,
|
|
141
176
|
identity_source: identitySource
|
|
@@ -164,7 +199,7 @@ function defaultAgentsMetaCounters() {
|
|
|
164
199
|
}
|
|
165
200
|
function deriveAgentsMetaStableId(file) {
|
|
166
201
|
const normalized = normalizePath(file);
|
|
167
|
-
if (normalized === "AGENTS.md"
|
|
202
|
+
if (normalized === "AGENTS.md") {
|
|
168
203
|
return "bootstrap";
|
|
169
204
|
}
|
|
170
205
|
return getDepthSource(normalized).replace(/\.md$/u, "");
|
|
@@ -181,7 +216,7 @@ function deriveAgentsMetaIdentitySource(node) {
|
|
|
181
216
|
}
|
|
182
217
|
function deriveAgentsMetaLayer(file) {
|
|
183
218
|
const normalized = normalizePath(file);
|
|
184
|
-
if (normalized === "AGENTS.md"
|
|
219
|
+
if (normalized === "AGENTS.md") {
|
|
185
220
|
return "L0";
|
|
186
221
|
}
|
|
187
222
|
if (hasCrossCuttingSegment(normalized)) {
|
|
@@ -292,31 +327,139 @@ var humanLockFileSchema = z4.object({
|
|
|
292
327
|
});
|
|
293
328
|
|
|
294
329
|
// src/schemas/fabric-config.ts
|
|
330
|
+
import { z as z6 } from "zod";
|
|
331
|
+
|
|
332
|
+
// src/schemas/store.ts
|
|
295
333
|
import { z as z5 } from "zod";
|
|
296
|
-
var
|
|
297
|
-
var
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
334
|
+
var STORE_UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u;
|
|
335
|
+
var storeUuidSchema = z5.string().regex(STORE_UUID_PATTERN, "store_uuid must be a canonical lowercase UUID");
|
|
336
|
+
var PERSONAL_STORE_SENTINEL = "$personal";
|
|
337
|
+
var storeIdentitySchema = z5.object({
|
|
338
|
+
// Intrinsic, immutable once minted. Read from store.json, never recomputed.
|
|
339
|
+
store_uuid: storeUuidSchema,
|
|
340
|
+
// ISO-8601. When the store was first initialized.
|
|
341
|
+
created_at: z5.string(),
|
|
342
|
+
// Optional human-facing canonical alias baked into the store (e.g. the
|
|
343
|
+
// team picks "platform-kb"). Local per-machine aliases are resolved by the
|
|
344
|
+
// StoreResolver from config and may differ; this is the suggested default.
|
|
345
|
+
canonical_alias: z5.string().optional(),
|
|
346
|
+
// Optional one-line description surfaced in `store list` / onboarding.
|
|
347
|
+
description: z5.string().optional(),
|
|
348
|
+
// The semantic scopes this store is *allowed* to hold. A shared (team)
|
|
349
|
+
// store MUST NOT list "personal" (R5#3 privacy boundary, enforced at write
|
|
350
|
+
// time in P2). Open coordinate strings — see schemas/scope.ts.
|
|
351
|
+
allowed_scopes: z5.array(z5.string()).optional()
|
|
352
|
+
}).strict();
|
|
353
|
+
var requiredStoreEntrySchema = z5.object({
|
|
354
|
+
id: z5.string().min(1),
|
|
355
|
+
suggested_remote: z5.union([z5.string().min(1), z5.literal(PERSONAL_STORE_SENTINEL)]).optional()
|
|
356
|
+
}).strict();
|
|
357
|
+
var STORE_KNOWLEDGE_TYPE_DIRS = [
|
|
358
|
+
"models",
|
|
359
|
+
"decisions",
|
|
360
|
+
"guidelines",
|
|
361
|
+
"pitfalls",
|
|
362
|
+
"processes"
|
|
363
|
+
];
|
|
364
|
+
var STORE_LAYOUT = {
|
|
365
|
+
identityFile: "store.json",
|
|
366
|
+
knowledgeDir: "knowledge",
|
|
367
|
+
bindingsDir: "bindings",
|
|
368
|
+
stateDir: "state"
|
|
369
|
+
};
|
|
370
|
+
var STORES_ROOT_DIR = "stores";
|
|
371
|
+
var GLOBAL_STATE_DIR = "state";
|
|
372
|
+
var GLOBAL_BINDINGS_DIR = "bindings";
|
|
373
|
+
function storeKnowledgeTypeDir(type) {
|
|
374
|
+
return `${STORE_LAYOUT.knowledgeDir}/${type}`;
|
|
375
|
+
}
|
|
376
|
+
function storeRelativePath(storeUuid) {
|
|
377
|
+
return `${STORES_ROOT_DIR}/${storeUuid}`;
|
|
378
|
+
}
|
|
379
|
+
var mountedStoreSchema = z5.object({
|
|
380
|
+
// Intrinsic identity of the mounted store (matches its store.json).
|
|
381
|
+
store_uuid: storeUuidSchema,
|
|
382
|
+
// Local per-machine alias the user references this store by (resolver maps
|
|
383
|
+
// alias → uuid). May differ from the store's canonical_alias.
|
|
384
|
+
alias: z5.string().min(1),
|
|
385
|
+
// Git remote locator for this clone, if any. Absent = local-only store
|
|
386
|
+
// (valid; doctor nudges to add a remote for backup — R5#5, P6).
|
|
387
|
+
remote: z5.string().min(1).optional(),
|
|
388
|
+
// v2.1.0-rc.1 P3: marks the implicit personal store (the one minted by
|
|
389
|
+
// `install --global`). Exactly one mounted store carries personal=true; it
|
|
390
|
+
// is the write target for personal-scope entries (R5#3) and always in the
|
|
391
|
+
// read-set (S11). Optional (no default) so the output type stays a plain
|
|
392
|
+
// optional — consumers coalesce `?? false` when building resolver input.
|
|
393
|
+
personal: z5.boolean().optional(),
|
|
394
|
+
// Whether writes are accepted into this store from this machine. Optional;
|
|
395
|
+
// consumers coalesce `?? true`. Shared stores cloned read-only set false.
|
|
396
|
+
writable: z5.boolean().optional()
|
|
302
397
|
}).strict();
|
|
303
|
-
var
|
|
304
|
-
|
|
305
|
-
|
|
398
|
+
var globalConfigSchema = z5.object({
|
|
399
|
+
// Machine/account identity. Personal-knowledge id namespace (S33/S27).
|
|
400
|
+
uid: z5.string().min(1),
|
|
401
|
+
// All stores mounted on this machine. The implicit personal store is
|
|
402
|
+
// included here once initialized. Default empty so a fresh global config
|
|
403
|
+
// (before `install --global`) parses cleanly.
|
|
404
|
+
stores: z5.array(mountedStoreSchema).optional().default([])
|
|
405
|
+
}).passthrough();
|
|
406
|
+
|
|
407
|
+
// src/schemas/fabric-config.ts
|
|
408
|
+
var auditModeSchema = z6.enum(["strict", "warn", "off"]);
|
|
409
|
+
var clientPathsSchema = z6.object({
|
|
410
|
+
claudeCodeCLI: z6.string().optional(),
|
|
411
|
+
claudeCodeDesktop: z6.string().optional(),
|
|
412
|
+
cursor: z6.string().optional(),
|
|
413
|
+
codexCLI: z6.string().optional()
|
|
414
|
+
}).strict();
|
|
415
|
+
var mcpPayloadLimitsSchema = z6.object({
|
|
416
|
+
warnBytes: z6.number().int().positive().optional(),
|
|
417
|
+
hardBytes: z6.number().int().positive().optional()
|
|
306
418
|
}).optional();
|
|
307
|
-
var
|
|
308
|
-
var
|
|
309
|
-
|
|
419
|
+
var selectionTokenTtlMsSchema = z6.number().int().min(3e4).max(36e5);
|
|
420
|
+
var fabricLanguageSchema = z6.enum([
|
|
421
|
+
"match-existing",
|
|
422
|
+
"zh-CN",
|
|
423
|
+
"en",
|
|
424
|
+
"zh-CN-hybrid"
|
|
425
|
+
]);
|
|
426
|
+
var defaultLayerFilterSchema = z6.enum(["team", "personal", "both"]);
|
|
427
|
+
var fabricConfigSchema = z6.object({
|
|
310
428
|
clientPaths: clientPathsSchema.optional(),
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
429
|
+
// v2.1.0-rc.1 P0 (S13-projectid): the project's stable identity. A UUID
|
|
430
|
+
// bound at `fabric install` time; a remote-derived hash is only a SUGGESTED
|
|
431
|
+
// default, never authoritative (so re-homing the git remote does not change
|
|
432
|
+
// project identity). Optional under the zero-user clean-slate — pre-v2.1
|
|
433
|
+
// fabric-config.json files simply lack it and the ProjectRootResolver mints
|
|
434
|
+
// one on next install. `.fabric/fabric-config.json` carrying this field is
|
|
435
|
+
// also the upward marker the ProjectRootResolver searches for (S15/S32).
|
|
436
|
+
project_id: z6.string().optional(),
|
|
437
|
+
// v2.1.0-rc.1 P0 (S59/B3): the stores this repo expects mounted. Each entry
|
|
438
|
+
// names a store by alias/UUID with an optional suggested_remote (or the
|
|
439
|
+
// `$personal` sentinel). Drives the read-set (required_stores ∪ implicit
|
|
440
|
+
// personal, S11/S54) and `clone`'s missing-store onboarding (S51). Optional
|
|
441
|
+
// + absent → read-set is just the implicit personal store.
|
|
442
|
+
required_stores: z6.array(requiredStoreEntrySchema).optional(),
|
|
443
|
+
// v2.1.0-rc.1 P3 (S60 / `store switch-write`): alias of the store that
|
|
444
|
+
// non-personal-scope writes land in for this project. Set by
|
|
445
|
+
// `fabric store switch-write <alias>`; consumed as the resolver's
|
|
446
|
+
// activeWriteAlias. Absent → no active write store yet. Personal-scope
|
|
447
|
+
// writes always target the implicit personal store regardless (R5#3).
|
|
448
|
+
active_write_store: z6.string().optional(),
|
|
449
|
+
// rc.17 (R-cut): the dev/test fixture-path config field was removed
|
|
450
|
+
// end-to-end. The `EXTERNAL_FIXTURE_PATH` env var is now the sole source
|
|
451
|
+
// consumed by `resolveDevMode()`. No z.preprocess alias — pre-rc.17
|
|
452
|
+
// fabric-config.json files carrying the field will be silently dropped by
|
|
453
|
+
// the lenient root parser (no .strict() at root). Pre-user clean-slate per
|
|
454
|
+
// memory/feedback_clean_slate.md; mirrors the rc.12 hard-rename precedent
|
|
455
|
+
// documented above.
|
|
456
|
+
scanIgnores: z6.array(z6.string()).optional(),
|
|
314
457
|
audit_mode: auditModeSchema.optional(),
|
|
315
458
|
mcpPayloadLimits: mcpPayloadLimitsSchema,
|
|
316
459
|
// Backward-compat: both fields are optional with defaults so existing
|
|
317
460
|
// fabric-config.json files (pre-grill-followup) parse unchanged. The default
|
|
318
461
|
// values themselves are load-bearing — see docs/data-schema.md.
|
|
319
|
-
|
|
462
|
+
fabric_language: fabricLanguageSchema.optional().default("match-existing"),
|
|
320
463
|
default_layer_filter: defaultLayerFilterSchema.optional().default("both"),
|
|
321
464
|
// Cooldown for the fabric-hint Stop hook (formerly archive-hint, renamed in
|
|
322
465
|
// rc.5 TASK-010). After ANY of the three signals (archive / review / import)
|
|
@@ -325,7 +468,7 @@ var fabricConfigSchema = z5.object({
|
|
|
325
468
|
// day if the user keeps ignoring it." Set to 24 to align with the archive
|
|
326
469
|
// trigger threshold. The legacy `archive_hint_` key is retained for backward
|
|
327
470
|
// compat with existing user fabric-config.json files.
|
|
328
|
-
archive_hint_cooldown_hours:
|
|
471
|
+
archive_hint_cooldown_hours: z6.number().int().positive().optional().default(12),
|
|
329
472
|
// Underseed-node threshold for the fabric-hint Stop hook's import signal
|
|
330
473
|
// (rc.5 TASK-010). When the canonical knowledge node count is strictly less
|
|
331
474
|
// than this value AND a successful `init_scan_completed` event happened at
|
|
@@ -334,7 +477,7 @@ var fabricConfigSchema = z5.object({
|
|
|
334
477
|
// the rule-of-thumb that a workspace with fewer than ten knowledge entries
|
|
335
478
|
// is below the floor for plan_context retrieval to be meaningful. Also
|
|
336
479
|
// consumed by `doctor` lint #22 (knowledge_underseeded).
|
|
337
|
-
underseed_node_threshold:
|
|
480
|
+
underseed_node_threshold: z6.number().int().positive().optional().default(10),
|
|
338
481
|
// Edit-count threshold for the fabric-hint Stop hook's Signal A
|
|
339
482
|
// (rc.6 TASK-022 / E5). Signal A fires when EITHER (a) >=24h have elapsed
|
|
340
483
|
// since the last `knowledge_proposed` event, OR (b) >=archive_edit_threshold
|
|
@@ -345,185 +488,1348 @@ var fabricConfigSchema = z5.object({
|
|
|
345
488
|
// there is probably something worth archiving"; lowered values nag more
|
|
346
489
|
// aggressively, higher values rely on the 24h fallback. Missing or absent
|
|
347
490
|
// edit-counter file degrades safely to the 24h-only path.
|
|
348
|
-
archive_edit_threshold:
|
|
491
|
+
archive_edit_threshold: z6.number().int().positive().optional().default(20),
|
|
349
492
|
// rc.7 T7: hours-since-last-knowledge_proposed cutoff for Signal A's
|
|
350
493
|
// time branch. Was hardcoded as 24 in fabric-hint.cjs's THRESHOLD_HOURS;
|
|
351
494
|
// externalized so chatty workspaces can lower the bar and quiet ones can
|
|
352
495
|
// raise it. Default 24 preserves rc.6 behavior. See docs/configuration.md.
|
|
353
|
-
archive_hint_hours:
|
|
496
|
+
archive_hint_hours: z6.number().int().positive().optional().default(24),
|
|
354
497
|
// rc.7 T7: pending-count cutoff for Signal B (review skill). Was
|
|
355
498
|
// hardcoded as 10 in fabric-hint.cjs's THRESHOLD_PENDING_COUNT.
|
|
356
499
|
// Default 10 preserves rc.6 behavior. See docs/configuration.md for
|
|
357
500
|
// small/medium/large repo recommendations.
|
|
358
|
-
review_hint_pending_count:
|
|
501
|
+
review_hint_pending_count: z6.number().int().positive().optional().default(10),
|
|
359
502
|
// rc.7 T7: pending-age cutoff (in days) for Signal B (review skill).
|
|
360
503
|
// Was hardcoded as 7 in fabric-hint.cjs's THRESHOLD_PENDING_AGE_DAYS.
|
|
361
504
|
// Default 7 preserves rc.6 behavior. See docs/configuration.md.
|
|
362
|
-
review_hint_pending_age_days:
|
|
505
|
+
review_hint_pending_age_days: z6.number().int().positive().optional().default(7),
|
|
363
506
|
// rc.7 T7 + T10 pre-wiring: days-since-last-doctor cutoff for the future
|
|
364
507
|
// Signal D (maintenance hint). T10 will consume this to decide when the
|
|
365
508
|
// fabric-hint Stop hook surfaces a "run `fabric doctor`" reminder.
|
|
366
509
|
// Default 14 reflects a fortnightly cadence — long enough to avoid nag,
|
|
367
510
|
// short enough to catch index drift before it compounds.
|
|
368
|
-
maintenance_hint_days:
|
|
511
|
+
maintenance_hint_days: z6.number().int().positive().optional().default(14),
|
|
369
512
|
// rc.7 T7 + T10 pre-wiring: cooldown between Signal D reminders, in
|
|
370
513
|
// days. Once Signal D fires, it stays silent for this many days even if
|
|
371
514
|
// the user doesn't run doctor. Default 7 keeps the reminder weekly at
|
|
372
515
|
// worst — pairing 14d trigger + 7d cooldown means at most ~2 reminders
|
|
373
516
|
// per month for a workspace that ignores them.
|
|
374
|
-
maintenance_hint_cooldown_days:
|
|
517
|
+
maintenance_hint_cooldown_days: z6.number().int().positive().optional().default(7),
|
|
518
|
+
// rc.9+ (skill-contract-fix B1): first-run import window in months. The
|
|
519
|
+
// `fabric-import` skill scans this many months of git history on the very
|
|
520
|
+
// first invocation (when no prior `import_run_completed` event exists).
|
|
521
|
+
// Default 60 (~5 years) captures the bulk of a mature repo's signal in
|
|
522
|
+
// one pass; small / fresh repos can lower to 12-24 with no loss.
|
|
523
|
+
import_window_first_run_months: z6.number().int().min(1).optional().default(60),
|
|
524
|
+
// rc.9+ (skill-contract-fix B1): rerun import window in months. After
|
|
525
|
+
// the first successful import, subsequent runs only scan this many
|
|
526
|
+
// recent months — assumed everything older has already been crystallized
|
|
527
|
+
// into pending or canonical knowledge. Default 2 keeps incremental cost
|
|
528
|
+
// low; raise to 6 if the workspace pauses fabric-import for long stretches.
|
|
529
|
+
import_window_rerun_months: z6.number().int().min(1).optional().default(2),
|
|
530
|
+
// rc.9+ (skill-contract-fix B1): hard cap on pending entries produced
|
|
531
|
+
// per fabric-import invocation. Prevents one run from dumping hundreds
|
|
532
|
+
// of proposals when a backfill window is wide open. Default 10 matches
|
|
533
|
+
// the rule-of-thumb "human can triage ~10 pending entries in one
|
|
534
|
+
// review pass." Range 1-50.
|
|
535
|
+
import_max_pending_per_run: z6.number().int().min(1).max(50).optional().default(10),
|
|
536
|
+
// rc.9+ (skill-contract-fix B1): hard cap on commits scanned per
|
|
537
|
+
// fabric-import invocation. Bounds runtime on monorepos with high
|
|
538
|
+
// commit velocity. Default 500 covers ~2 months of typical churn;
|
|
539
|
+
// range 50-2000. Hitting the cap mid-window is logged but non-fatal.
|
|
540
|
+
import_max_commits_scan: z6.number().int().min(50).max(2e3).optional().default(500),
|
|
541
|
+
// rc.9+ (skill-contract-fix B1): canonical-node count above which
|
|
542
|
+
// fabric-import's pre-flight should warn / suggest review instead of
|
|
543
|
+
// proceeding. A workspace with 50+ canonical entries usually benefits
|
|
544
|
+
// more from `fabric-review` to consolidate than from importing more.
|
|
545
|
+
// Default 50; raise to 100+ for large polyglot repos.
|
|
546
|
+
import_skip_canonical_threshold: z6.number().int().positive().optional().default(50),
|
|
547
|
+
// rc.9+ (skill-contract-fix B1): max candidate entries surfaced per
|
|
548
|
+
// fabric-archive batch (one invocation of the skill). Pagination knob
|
|
549
|
+
// for the archive UI flow. Default 8 keeps each batch reviewable in
|
|
550
|
+
// one sitting; raise for large repos with high archive throughput.
|
|
551
|
+
archive_max_candidates_per_batch: z6.number().int().positive().optional().default(8),
|
|
552
|
+
// rc.9+ (skill-contract-fix B1): max recently-touched paths included
|
|
553
|
+
// in fabric-archive's "relevant context" lookup. Limits the size of
|
|
554
|
+
// the path-relevance digest the skill emits when ranking candidates.
|
|
555
|
+
// Default 20; large repos with deep directory fan-out can raise to
|
|
556
|
+
// 50+ if archive candidates feel under-contextualized.
|
|
557
|
+
archive_max_recent_paths: z6.number().int().positive().optional().default(20),
|
|
558
|
+
// rc.9+ (skill-contract-fix B1): max prior fabric-archive sessions
|
|
559
|
+
// summarised in the digest the skill loads on start. Prevents the
|
|
560
|
+
// digest from ballooning past the model context budget on workspaces
|
|
561
|
+
// that have archived repeatedly. Default 10; lower if context pressure
|
|
562
|
+
// bites, raise if you want longer-range archive trend visibility.
|
|
563
|
+
archive_digest_max_sessions: z6.number().int().positive().optional().default(10),
|
|
564
|
+
// rc.9+ (skill-contract-fix B1): max review results returned per
|
|
565
|
+
// topic when `fabric-review` clusters pending entries. Pagination
|
|
566
|
+
// knob analogous to archive_max_candidates_per_batch but scoped to
|
|
567
|
+
// each topic cluster. Default 8; raise to 15-20 for large repos
|
|
568
|
+
// where each topic legitimately groups many pending entries.
|
|
569
|
+
review_topic_result_cap: z6.number().int().positive().optional().default(8),
|
|
570
|
+
// rc.9+ (skill-contract-fix B1): age threshold (in days) above which
|
|
571
|
+
// a pending entry is considered "stale" by fabric-review and surfaced
|
|
572
|
+
// for explicit resolve-or-drop decision. Default 14; tighter than the
|
|
573
|
+
// 7d Signal-B trigger because review specifically targets the long
|
|
574
|
+
// tail. Large repos with slower cadence can raise to 30.
|
|
575
|
+
review_stale_pending_days: z6.number().int().positive().optional().default(14),
|
|
576
|
+
// v2.0.0-rc.34 TASK-05: reverse-unarchive opt-in. When true, callers of the
|
|
577
|
+
// `unarchiveKnowledge` primitive (and any future doctor auto-detect lint built
|
|
578
|
+
// on top) will execute the file move + ledger emit. When false (default),
|
|
579
|
+
// the same callers MUST short-circuit before any mutation — the primitive is
|
|
580
|
+
// shipped but inert until explicitly enabled. Opt-in posture mirrors the
|
|
581
|
+
// archive-flow precedent: destructive-ish file moves stay behind a flag.
|
|
582
|
+
reverse_unarchive_enabled: z6.boolean().optional().default(false),
|
|
583
|
+
// v2.0.0-rc.34 TASK-05: forces `unarchiveKnowledge` into dry-run mode even
|
|
584
|
+
// when called with `options.dryRun=false`. Lets operators preview a
|
|
585
|
+
// restoration pass before flipping `reverse_unarchive_enabled` to true.
|
|
586
|
+
reverse_unarchive_dry_run: z6.boolean().optional().default(false),
|
|
587
|
+
// v2.0.0-rc.34 TASK-06: long-session cite-policy evict window in user-prompt
|
|
588
|
+
// turns. UserPromptSubmit hook (Claude Code only) maintains a per-session
|
|
589
|
+
// counter and re-injects the cite contract reminder via
|
|
590
|
+
// hookSpecificOutput.additionalContext when `turn_count % interval === 0`.
|
|
591
|
+
// Default 0 = OFF (opt-in). Recommend 10-20 for active sessions; 5 for
|
|
592
|
+
// high-contract-criticality projects. Other strategies (time-based,
|
|
593
|
+
// token-budget) deferred to rc.35 per plan locked-decisions 2026-05-26.
|
|
594
|
+
cite_evict_interval: z6.number().int().min(0).optional().default(0),
|
|
595
|
+
// v2.0.0-rc.22 Scope A T3: sliding-window retention (in days) for the
|
|
596
|
+
// event ledger rotation primitive (`rotateEventLedgerIfNeeded`). Lines
|
|
597
|
+
// whose `ts` is older than `now - fabric_event_retention_days * 86_400_000`
|
|
598
|
+
// are partitioned into `.fabric/events.archive/events-rotated-YYYY-MM-DD.jsonl`.
|
|
599
|
+
// Locked to 7/30/90 — three operator-friendly preset windows. Default 30
|
|
600
|
+
// is applied at the consumer site (rotateEventLedgerIfNeeded), so this
|
|
601
|
+
// field stays `.optional()` without a `.default()` to keep the schema
|
|
602
|
+
// surface honest: absence means "use the library default", not "schema
|
|
603
|
+
// default of 30 was injected." 7 = ~tight, 30 = balanced, 90 = forensic.
|
|
604
|
+
// Mirrors cite-policy precedent of locking enum-style numeric tunables
|
|
605
|
+
// to a small literal set (vs free `.positive()`) to prevent fat-finger
|
|
606
|
+
// misconfig.
|
|
607
|
+
fabric_event_retention_days: z6.union([z6.literal(7), z6.literal(30), z6.literal(90)]).optional(),
|
|
608
|
+
// v2.0.0-rc.23 TASK-014 (F8c): onboard slot opt-out list. Tracks slot
|
|
609
|
+
// names the user explicitly dismissed during fabric-archive's first-run
|
|
610
|
+
// onboard phase (or via `fabric config dismiss-slot <slot>`). Dismissed
|
|
611
|
+
// slots are excluded from `fabric onboard-coverage`'s `missing` set and the
|
|
612
|
+
// doctor `Onboard coverage` advisory's recompute, so the user is never
|
|
613
|
+
// re-prompted for slots they consciously declined.
|
|
614
|
+
//
|
|
615
|
+
// Re-opening a dismissed slot requires `fabric config onboard-reset <slot>`
|
|
616
|
+
// — a deliberate two-command UX to keep the dismiss intent reversible
|
|
617
|
+
// but never silently undone. Schema is intentionally `z.array(z.string())`
|
|
618
|
+
// rather than `z.array(onboardSlotSchema)` so historical configs survive
|
|
619
|
+
// a slot rename without a Zod parse error; downstream consumers
|
|
620
|
+
// intersect against ONBOARD_SLOT_NAMES at read time.
|
|
621
|
+
//
|
|
622
|
+
// Default `[]` keeps the field optional on existing configs — fresh
|
|
623
|
+
// installs land with no opt-outs.
|
|
624
|
+
onboard_slots_opted_out: z6.array(z6.string()).optional().default([]),
|
|
625
|
+
// v2.0.0-rc.33 W2-1 (P0-9): TopK upper bound for the broad SessionStart hint
|
|
626
|
+
// banner emitted by knowledge-hint-broad.cjs. After plan-context-hint returns
|
|
627
|
+
// its full broad-scoped index, the hook slices the entries to this many
|
|
628
|
+
// before grouping/truncation rendering — keeps the banner from scrolling off
|
|
629
|
+
// screen on well-seeded repos (Werewolf-class projects routinely surface 40+
|
|
630
|
+
// broad entries which buried the actually-relevant top hits). Default 8 is
|
|
631
|
+
// calibrated against the rc.32 eval baseline (cite-coverage 3.1%): the
|
|
632
|
+
// banner needs to fit in ~1 screenful so the agent actually reads it.
|
|
633
|
+
// Range 1..50; values above 20 effectively disable the cap because the
|
|
634
|
+
// TRUNCATION_THRESHOLD=12 grouped-render kicks in. Mirrors the rc.7 T7 +
|
|
635
|
+
// archive_max_* pattern of externalizing previously-hardcoded thresholds.
|
|
636
|
+
hint_broad_top_k: z6.number().int().min(1).max(50).optional().default(8),
|
|
637
|
+
// v2.0.0-rc.37 NEW-16: durable per-signal dismiss for the fabric-hint Stop
|
|
638
|
+
// hook nudges. Any signal type listed here is suppressed at emit time across
|
|
639
|
+
// all sessions (the session-scoped sibling lives in a .fabric/.cache sidecar
|
|
640
|
+
// written on request). Mirrors the cite_evict_interval=0 opt-out convention —
|
|
641
|
+
// a knob for an existing surface, not a new feature. Unknown types ignored.
|
|
642
|
+
hint_dismiss_signals: z6.array(z6.enum(["archive", "review", "import", "maintenance"])).optional(),
|
|
643
|
+
// v2.0.0-rc.33 W2-1 (P0-9): TopK upper bound for the narrow PreToolUse hint
|
|
644
|
+
// emitted by knowledge-hint-narrow.cjs. After filtering to entries whose
|
|
645
|
+
// `relevance_scope === "narrow"` (rc.27 TASK-005 audit §2.5 fix), the hook
|
|
646
|
+
// slices to this many before the E3 emit-gate / renderSummary pipeline.
|
|
647
|
+
// Default 5 keeps each per-Edit hint terse — five lines max so the agent's
|
|
648
|
+
// working memory is not displaced by an unwieldy banner. Range 1..20.
|
|
649
|
+
hint_narrow_top_k: z6.number().int().min(1).max(20).optional().default(5),
|
|
650
|
+
// v2.0.0-rc.33 W2-1 (P0-9): per-file dedup window (in PreToolUse turns) for
|
|
651
|
+
// the narrow hint. Same (file_path, stable_id) tuple stays silent for this
|
|
652
|
+
// many turns even when the E3 cross-session cache would otherwise re-emit.
|
|
653
|
+
// Closes the rc.32 eval finding that a single hot file (e.g. werewolf
|
|
654
|
+
// GameRoom.tsx edited 30 times in a row) re-fired the same narrow hint
|
|
655
|
+
// each time, training the agent to ignore it. Default 5; range 1..50.
|
|
656
|
+
// Storage: .fabric/.cache/narrow-dedup-window.json — distinct from session-
|
|
657
|
+
// hints cache so a window-only suppression does not poison cross-session
|
|
658
|
+
// dedupe semantics.
|
|
659
|
+
hint_narrow_dedup_window_turns: z6.number().int().min(1).max(50).optional().default(5),
|
|
660
|
+
// v2.0.0-rc.33 W2-5 (P1-8): cooldown between broad SessionStart hint emits,
|
|
661
|
+
// in hours. Distinct from the archive_hint_cooldown_hours that gates the
|
|
662
|
+
// fabric-hint Stop hook — knowledge-hint-broad re-fires on every
|
|
663
|
+
// SessionStart by default (compact / clear / new-window), which on long
|
|
664
|
+
// sessions becomes redundant noise. Setting to 1 means "emit the broad
|
|
665
|
+
// menu at most once per hour"; 0 means "no cooldown, current behavior."
|
|
666
|
+
// Range 0..168 (one week). Stored alongside fabric-hint's cooldown cache
|
|
667
|
+
// under a distinct knowledge-hint-broad key.
|
|
668
|
+
hint_broad_cooldown_hours: z6.number().int().min(0).max(168).optional().default(0),
|
|
669
|
+
// v2.0.0-rc.33 W2-5 (P1-8): cooldown for the narrow PreToolUse hint.
|
|
670
|
+
// Same shape as hint_broad_cooldown_hours but applies to per-Edit hint
|
|
671
|
+
// re-emission across the cooldown window — independent of E3 session-
|
|
672
|
+
// hints dedupe. Default 0 preserves rc.32 behavior; set to e.g. 1 to
|
|
673
|
+
// throttle hint frequency during rapid-fire editing sprints. Range
|
|
674
|
+
// 0..168 (one week).
|
|
675
|
+
hint_narrow_cooldown_hours: z6.number().int().min(0).max(168).optional().default(0),
|
|
676
|
+
// v2.0.0-rc.33 W4-B3 (T5 P2): per-maturity inactivity thresholds (days)
|
|
677
|
+
// driving orphan_demote. Hardcoded at stable=90/endorsed=30/draft=14 in
|
|
678
|
+
// rc.32; chatty workspaces want them tighter, slow ones want them looser.
|
|
679
|
+
// Each field optional; absent → defaults inside doctor.ts apply. Ranges
|
|
680
|
+
// chosen so a typo can't accidentally disable the lint (min 1).
|
|
681
|
+
orphan_demote_stable_days: z6.number().int().min(1).max(3650).optional(),
|
|
682
|
+
orphan_demote_endorsed_days: z6.number().int().min(1).max(3650).optional(),
|
|
683
|
+
orphan_demote_draft_days: z6.number().int().min(1).max(3650).optional(),
|
|
684
|
+
// v2.0.0-rc.33 W4-A3 (T4 P2): per-entry summary truncation length used by
|
|
685
|
+
// knowledge-hint-{broad,narrow}.cjs. Hard-coded at 80 chars in rc.32 — too
|
|
686
|
+
// short for entries with parameterized summaries (e.g. "Use bcrypt with
|
|
687
|
+
// cost=12 for password hashing"), too long for terse pitfalls. Range 40..240;
|
|
688
|
+
// default 80 preserves rc.32 behavior. Both hooks read the same key so the
|
|
689
|
+
// banner styling stays consistent across SessionStart + PreToolUse.
|
|
690
|
+
hint_summary_max_len: z6.number().int().min(40).max(240).optional().default(80),
|
|
691
|
+
// v2.0.0-rc.33 W2-6 (P0-7 + P0-8): when true, knowledge-hint hooks emit
|
|
692
|
+
// their banners as `hookSpecificOutput.additionalContext` JSON on stdout
|
|
693
|
+
// (per Claude Code PreToolUse hook contract — see
|
|
694
|
+
// https://docs.claude.com/en/docs/claude-code/hooks#preToolUse), so the
|
|
695
|
+
// agent receives them in-context instead of as stderr breadcrumbs the
|
|
696
|
+
// user may not surface to the model. Default true reflects the rc.33 cite-
|
|
697
|
+
// coverage focus (rc.32 baseline 3.1% → primary cause: reminders never
|
|
698
|
+
// entered model context). Set false to revert to legacy stderr-only mode
|
|
699
|
+
// for hosts that don't honor the JSON contract.
|
|
700
|
+
hint_reminder_to_context: z6.boolean().optional().default(true),
|
|
701
|
+
// v2.0.0-rc.29 TASK-008 (BUG-F3): selection-token TTL override. The
|
|
702
|
+
// `fab_plan_context` MCP tool hands clients a `selection_token` whose default
|
|
703
|
+
// 5-minute lifetime (`SELECTION_TOKEN_TTL_MS` at
|
|
704
|
+
// packages/server/src/services/plan-context.ts:91) was hard-coded and could
|
|
705
|
+
// not be tuned for slow review cycles. Operators on long-running sessions
|
|
706
|
+
// (manual paste-and-review flows, debugger pauses, etc.) reported tokens
|
|
707
|
+
// expiring mid-review. Override here; absence means "use the library default
|
|
708
|
+
// of 5*60*1000 ms." Range 30s..1h keeps the value useful — below 30s the
|
|
709
|
+
// token expires before MCP round-trips finish; above 1h it stops being a
|
|
710
|
+
// meaningful liveness signal for the plan-context cache.
|
|
711
|
+
//
|
|
712
|
+
// The single-field schema is exported separately (`selectionTokenTtlMsSchema`)
|
|
713
|
+
// so the server-side per-field reader can validate without re-running the
|
|
714
|
+
// whole fabricConfigSchema on every plan_context call — that lets a corrupt
|
|
715
|
+
// unrelated field stay isolated from the hot read path.
|
|
716
|
+
selection_token_ttl_ms: selectionTokenTtlMsSchema.optional()
|
|
717
|
+
});
|
|
718
|
+
|
|
719
|
+
// src/schemas/fabric-config-introspect.ts
|
|
720
|
+
import { z as z7 } from "zod";
|
|
721
|
+
var positiveIntSchema = z7.coerce.number().int().positive();
|
|
722
|
+
function makePositiveIntField(key, defaultValue) {
|
|
723
|
+
return {
|
|
724
|
+
key,
|
|
725
|
+
group: "B_hint_threshold",
|
|
726
|
+
widget: "text",
|
|
727
|
+
label_i18n_key: `cli.config.fields.${key}.label`,
|
|
728
|
+
description_i18n_key: `cli.config.fields.${key}.description`,
|
|
729
|
+
default: defaultValue,
|
|
730
|
+
validate(raw) {
|
|
731
|
+
const trimmed = raw.trim();
|
|
732
|
+
if (trimmed === "") {
|
|
733
|
+
return { ok: false, error: "Value is required (positive integer)." };
|
|
734
|
+
}
|
|
735
|
+
const parsed = positiveIntSchema.safeParse(trimmed);
|
|
736
|
+
if (!parsed.success) {
|
|
737
|
+
return {
|
|
738
|
+
ok: false,
|
|
739
|
+
error: "Must be a positive integer (e.g. 1, 12, 24)."
|
|
740
|
+
};
|
|
741
|
+
}
|
|
742
|
+
return { ok: true, value: parsed.data };
|
|
743
|
+
},
|
|
744
|
+
format_for_display(value) {
|
|
745
|
+
if (typeof value === "number") return String(value);
|
|
746
|
+
if (value === void 0 || value === null) return String(defaultValue);
|
|
747
|
+
return String(value);
|
|
748
|
+
}
|
|
749
|
+
};
|
|
750
|
+
}
|
|
751
|
+
function makeEnumField(key, group, enumValues, defaultValue) {
|
|
752
|
+
return {
|
|
753
|
+
key,
|
|
754
|
+
group,
|
|
755
|
+
widget: "select",
|
|
756
|
+
label_i18n_key: `cli.config.fields.${key}.label`,
|
|
757
|
+
description_i18n_key: `cli.config.fields.${key}.description`,
|
|
758
|
+
default: defaultValue,
|
|
759
|
+
enum_values: enumValues,
|
|
760
|
+
validate(raw) {
|
|
761
|
+
const trimmed = raw.trim();
|
|
762
|
+
if (!enumValues.includes(trimmed)) {
|
|
763
|
+
return {
|
|
764
|
+
ok: false,
|
|
765
|
+
error: `Must be one of: ${enumValues.join(", ")}.`
|
|
766
|
+
};
|
|
767
|
+
}
|
|
768
|
+
return { ok: true, value: trimmed };
|
|
769
|
+
},
|
|
770
|
+
format_for_display(value) {
|
|
771
|
+
if (typeof value === "string" && enumValues.includes(value)) return value;
|
|
772
|
+
if (value === void 0 || value === null) return defaultValue;
|
|
773
|
+
return String(value);
|
|
774
|
+
}
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
var SCHEMA_DEFAULTS = fabricConfigSchema.parse({});
|
|
778
|
+
function pickNumberDefault(key) {
|
|
779
|
+
const v = SCHEMA_DEFAULTS[key];
|
|
780
|
+
if (typeof v !== "number") {
|
|
781
|
+
throw new Error(
|
|
782
|
+
`fabric-config-introspect: expected numeric default for ${String(key)}, got ${typeof v}`
|
|
783
|
+
);
|
|
784
|
+
}
|
|
785
|
+
return v;
|
|
786
|
+
}
|
|
787
|
+
function pickStringDefault(key) {
|
|
788
|
+
const v = SCHEMA_DEFAULTS[key];
|
|
789
|
+
if (typeof v !== "string") {
|
|
790
|
+
throw new Error(
|
|
791
|
+
`fabric-config-introspect: expected string default for ${String(key)}, got ${typeof v}`
|
|
792
|
+
);
|
|
793
|
+
}
|
|
794
|
+
return v;
|
|
795
|
+
}
|
|
796
|
+
var AUDIT_MODE_PANEL_DEFAULT = "warn";
|
|
797
|
+
function getPanelFields() {
|
|
798
|
+
return PANEL_FIELDS;
|
|
799
|
+
}
|
|
800
|
+
function getPanelFieldByKey(key) {
|
|
801
|
+
return PANEL_FIELDS.find((f) => f.key === key);
|
|
802
|
+
}
|
|
803
|
+
var PANEL_FIELDS = [
|
|
804
|
+
// --- Group A: Locale (2) ---
|
|
805
|
+
makeEnumField(
|
|
806
|
+
"fabric_language",
|
|
807
|
+
"A_locale",
|
|
808
|
+
fabricLanguageSchema.options,
|
|
809
|
+
pickStringDefault("fabric_language")
|
|
810
|
+
),
|
|
811
|
+
makeEnumField(
|
|
812
|
+
"default_layer_filter",
|
|
813
|
+
"A_locale",
|
|
814
|
+
defaultLayerFilterSchema.options,
|
|
815
|
+
pickStringDefault("default_layer_filter")
|
|
816
|
+
),
|
|
817
|
+
// --- Group B: Hint thresholds (8 — see leading docstring for the
|
|
818
|
+
// 7-vs-8 reconciliation; archive_edit_threshold is the 8th key) ---
|
|
819
|
+
makePositiveIntField("archive_hint_hours", pickNumberDefault("archive_hint_hours")),
|
|
820
|
+
makePositiveIntField(
|
|
821
|
+
"archive_hint_cooldown_hours",
|
|
822
|
+
pickNumberDefault("archive_hint_cooldown_hours")
|
|
823
|
+
),
|
|
824
|
+
makePositiveIntField(
|
|
825
|
+
"archive_edit_threshold",
|
|
826
|
+
pickNumberDefault("archive_edit_threshold")
|
|
827
|
+
),
|
|
828
|
+
makePositiveIntField(
|
|
829
|
+
"underseed_node_threshold",
|
|
830
|
+
pickNumberDefault("underseed_node_threshold")
|
|
831
|
+
),
|
|
832
|
+
makePositiveIntField(
|
|
833
|
+
"review_hint_pending_count",
|
|
834
|
+
pickNumberDefault("review_hint_pending_count")
|
|
835
|
+
),
|
|
836
|
+
makePositiveIntField(
|
|
837
|
+
"review_hint_pending_age_days",
|
|
838
|
+
pickNumberDefault("review_hint_pending_age_days")
|
|
839
|
+
),
|
|
840
|
+
makePositiveIntField(
|
|
841
|
+
"maintenance_hint_days",
|
|
842
|
+
pickNumberDefault("maintenance_hint_days")
|
|
843
|
+
),
|
|
844
|
+
makePositiveIntField(
|
|
845
|
+
"maintenance_hint_cooldown_days",
|
|
846
|
+
pickNumberDefault("maintenance_hint_cooldown_days")
|
|
847
|
+
),
|
|
848
|
+
// --- Group C: Audit (1) ---
|
|
849
|
+
makeEnumField(
|
|
850
|
+
"audit_mode",
|
|
851
|
+
"C_audit",
|
|
852
|
+
auditModeSchema.options,
|
|
853
|
+
AUDIT_MODE_PANEL_DEFAULT
|
|
854
|
+
)
|
|
855
|
+
];
|
|
856
|
+
|
|
857
|
+
// src/schemas/scope.ts
|
|
858
|
+
import { z as z8 } from "zod";
|
|
859
|
+
var PERSONAL_SCOPE = "personal";
|
|
860
|
+
var KNOWN_SCOPE_PREFIXES = ["personal", "team", "project", "org"];
|
|
861
|
+
var SCOPE_COORDINATE_PATTERN = /^[a-z0-9_-]+(:[a-z0-9_-]+)*$/u;
|
|
862
|
+
var scopeCoordinateSchema = z8.string().min(1).regex(
|
|
863
|
+
SCOPE_COORDINATE_PATTERN,
|
|
864
|
+
"scope coordinate must be ':'-joined lowercase [a-z0-9_-] segments"
|
|
865
|
+
);
|
|
866
|
+
function scopeRoot(coordinate) {
|
|
867
|
+
const colon = coordinate.indexOf(":");
|
|
868
|
+
return colon === -1 ? coordinate : coordinate.slice(0, colon);
|
|
869
|
+
}
|
|
870
|
+
function isPersonalScope(coordinate) {
|
|
871
|
+
return scopeRoot(coordinate) === PERSONAL_SCOPE;
|
|
872
|
+
}
|
|
873
|
+
var entryScopeMetadataSchema = z8.object({
|
|
874
|
+
semantic_scope: scopeCoordinateSchema,
|
|
875
|
+
// Store alias or UUID. Validated as a non-empty string here; the resolver
|
|
876
|
+
// (P0.6) maps alias→UUID and verifies the store is in the read-set.
|
|
877
|
+
visibility_store: z8.string().min(1)
|
|
878
|
+
}).strict();
|
|
879
|
+
|
|
880
|
+
// src/schemas/store-stable-id.ts
|
|
881
|
+
import { z as z9 } from "zod";
|
|
882
|
+
var localKnowledgeIdSchema = StableIdSchema;
|
|
883
|
+
var UID_SEGMENT_PATTERN = /^[a-z0-9-]+$/u;
|
|
884
|
+
var uidSchema = z9.string().min(1).regex(UID_SEGMENT_PATTERN, "uid must be lowercase [a-z0-9-] segments");
|
|
885
|
+
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;
|
|
886
|
+
var globalRefSchema = z9.string().regex(GLOBAL_REF_PATTERN, "global_ref must be <store_uuid>[:<uid>]:<local_id>");
|
|
887
|
+
function formatGlobalRef(parts) {
|
|
888
|
+
const { store_uuid, uid, local_id } = parts;
|
|
889
|
+
return uid === void 0 ? `${store_uuid}:${local_id}` : `${store_uuid}:${uid}:${local_id}`;
|
|
890
|
+
}
|
|
891
|
+
function parseGlobalRef(ref) {
|
|
892
|
+
if (!GLOBAL_REF_PATTERN.test(ref)) {
|
|
893
|
+
return null;
|
|
894
|
+
}
|
|
895
|
+
const localMatch = ref.match(/K[PT]-(?:MOD|DEC|GLD|PIT|PRO)-\d{4,}$/u);
|
|
896
|
+
if (localMatch === null) {
|
|
897
|
+
return null;
|
|
898
|
+
}
|
|
899
|
+
const local_id = localMatch[0];
|
|
900
|
+
const head = ref.slice(0, ref.length - local_id.length - 1);
|
|
901
|
+
const firstColon = head.indexOf(":");
|
|
902
|
+
if (firstColon === -1) {
|
|
903
|
+
return { store_uuid: head, local_id };
|
|
904
|
+
}
|
|
905
|
+
return {
|
|
906
|
+
store_uuid: head.slice(0, firstColon),
|
|
907
|
+
uid: head.slice(firstColon + 1),
|
|
908
|
+
local_id
|
|
909
|
+
};
|
|
910
|
+
}
|
|
911
|
+
var storeKnowledgeTypeCountersSchema = z9.object({
|
|
912
|
+
MOD: z9.number().int().nonnegative().default(0),
|
|
913
|
+
DEC: z9.number().int().nonnegative().default(0),
|
|
914
|
+
GLD: z9.number().int().nonnegative().default(0),
|
|
915
|
+
PIT: z9.number().int().nonnegative().default(0),
|
|
916
|
+
PRO: z9.number().int().nonnegative().default(0)
|
|
917
|
+
}).default({ MOD: 0, DEC: 0, GLD: 0, PIT: 0, PRO: 0 });
|
|
918
|
+
var storeCountersSchema = z9.object({
|
|
919
|
+
KP: storeKnowledgeTypeCountersSchema,
|
|
920
|
+
KT: storeKnowledgeTypeCountersSchema
|
|
921
|
+
}).default({
|
|
922
|
+
KP: { MOD: 0, DEC: 0, GLD: 0, PIT: 0, PRO: 0 },
|
|
923
|
+
KT: { MOD: 0, DEC: 0, GLD: 0, PIT: 0, PRO: 0 }
|
|
375
924
|
});
|
|
376
925
|
|
|
926
|
+
// src/schemas/parity-matrix.ts
|
|
927
|
+
import { z as z10 } from "zod";
|
|
928
|
+
var PARITY_CLIENTS = ["claudeCode", "codexCLI", "cursor"];
|
|
929
|
+
var parityClientSchema = z10.enum(PARITY_CLIENTS);
|
|
930
|
+
var PARITY_SURFACES = ["skill", "hook", "mcp", "render"];
|
|
931
|
+
var paritySurfaceSchema = z10.enum(PARITY_SURFACES);
|
|
932
|
+
var parityClientExpectationSchema = z10.object({
|
|
933
|
+
supported: z10.boolean(),
|
|
934
|
+
mechanism: z10.string().optional(),
|
|
935
|
+
notes: z10.string().optional()
|
|
936
|
+
}).strict();
|
|
937
|
+
var parityCapabilitySchema = z10.object({
|
|
938
|
+
id: z10.string().min(1),
|
|
939
|
+
surface: paritySurfaceSchema,
|
|
940
|
+
description: z10.string().min(1),
|
|
941
|
+
clients: z10.object({
|
|
942
|
+
claudeCode: parityClientExpectationSchema,
|
|
943
|
+
codexCLI: parityClientExpectationSchema,
|
|
944
|
+
cursor: parityClientExpectationSchema
|
|
945
|
+
}).strict()
|
|
946
|
+
}).strict();
|
|
947
|
+
var parityMatrixSchema = z10.object({
|
|
948
|
+
// Schema/version tag of the matrix document itself.
|
|
949
|
+
version: z10.string().min(1),
|
|
950
|
+
// Free-form note on what release/milestone this matrix targets.
|
|
951
|
+
generated_for: z10.string().min(1),
|
|
952
|
+
capabilities: z10.array(parityCapabilitySchema).min(1)
|
|
953
|
+
}).strict();
|
|
954
|
+
|
|
955
|
+
// src/resolver/contracts.ts
|
|
956
|
+
import { z as z11 } from "zod";
|
|
957
|
+
var PROJECT_ROOT_SIGNALS = ["env", "marker", "cwd", "repo"];
|
|
958
|
+
var projectRootSignalSchema = z11.enum(PROJECT_ROOT_SIGNALS);
|
|
959
|
+
var projectRootSignalsSchema = z11.object({
|
|
960
|
+
// FABRIC_PROJECT_ROOT, if set.
|
|
961
|
+
env: z11.string().optional(),
|
|
962
|
+
// Nearest directory AT-OR-ABOVE cwd holding `.fabric/fabric-config.json`,
|
|
963
|
+
// if any (the upward marker search result; may equal cwd).
|
|
964
|
+
markerDir: z11.string().optional(),
|
|
965
|
+
// Always present — the process cwd.
|
|
966
|
+
cwd: z11.string().min(1),
|
|
967
|
+
// git repo root, if inside a repo.
|
|
968
|
+
repoRoot: z11.string().optional(),
|
|
969
|
+
// The `project_id` read from the winning root's fabric-config.json during
|
|
970
|
+
// (fs) signal collection. The pure resolver echoes it — it cannot invent a
|
|
971
|
+
// UUID. Worktrees of one repo share the committed config, hence the same
|
|
972
|
+
// project_id (S45 merge). Absent when no .fabric config exists at the root
|
|
973
|
+
// yet (fresh repo-fallback) → resolution still yields the root with a null
|
|
974
|
+
// projectId so the caller can mint+persist one at install time.
|
|
975
|
+
discoveredProjectId: z11.string().optional()
|
|
976
|
+
}).strict();
|
|
977
|
+
var projectRootResolutionSchema = z11.object({
|
|
978
|
+
// Absolute project root directory.
|
|
979
|
+
projectRoot: z11.string().min(1),
|
|
980
|
+
// Stable project identity. One repo = one .fabric = one project_id (S32);
|
|
981
|
+
// git worktrees of the same repo resolve to the SAME project_id (S45).
|
|
982
|
+
// Null when the resolved root has no fabric-config.json yet (fresh
|
|
983
|
+
// repo-fallback) — the caller mints + persists a UUID at install time.
|
|
984
|
+
projectId: z11.string().min(1).nullable(),
|
|
985
|
+
// Which signal won.
|
|
986
|
+
signalUsed: projectRootSignalSchema
|
|
987
|
+
}).strict();
|
|
988
|
+
var STORE_RESOLVER_WARNING_CODES = [
|
|
989
|
+
"missing_store",
|
|
990
|
+
// required_stores entry has no matching mounted store (S51)
|
|
991
|
+
"local_only_no_remote",
|
|
992
|
+
// mounted but local-only (R5#5 nudge, non-fatal)
|
|
993
|
+
"alias_unresolved"
|
|
994
|
+
// referenced alias maps to no mounted store
|
|
995
|
+
];
|
|
996
|
+
var storeResolverWarningCodeSchema = z11.enum(STORE_RESOLVER_WARNING_CODES);
|
|
997
|
+
var storeResolverWarningSchema = z11.object({
|
|
998
|
+
code: storeResolverWarningCodeSchema,
|
|
999
|
+
// The alias/UUID/id the warning concerns.
|
|
1000
|
+
ref: z11.string().min(1),
|
|
1001
|
+
message: z11.string().min(1)
|
|
1002
|
+
}).strict();
|
|
1003
|
+
var readSetEntrySchema = z11.object({
|
|
1004
|
+
store_uuid: z11.string().min(1),
|
|
1005
|
+
alias: z11.string().min(1),
|
|
1006
|
+
remote: z11.string().min(1).optional(),
|
|
1007
|
+
// Whether this store accepts writes from the current context. Personal
|
|
1008
|
+
// store is writable; shared stores writable iff mounted with write intent.
|
|
1009
|
+
writable: z11.boolean()
|
|
1010
|
+
}).strict();
|
|
1011
|
+
var storeReadSetSchema = z11.object({
|
|
1012
|
+
stores: z11.array(readSetEntrySchema),
|
|
1013
|
+
warnings: z11.array(storeResolverWarningSchema)
|
|
1014
|
+
}).strict();
|
|
1015
|
+
var writeTargetSchema = z11.object({
|
|
1016
|
+
store_uuid: z11.string().min(1),
|
|
1017
|
+
alias: z11.string().min(1)
|
|
1018
|
+
}).strict();
|
|
1019
|
+
var storeResolveInputSchema = z11.object({
|
|
1020
|
+
// Machine identity (S33) — namespaces personal ids; identifies personal store.
|
|
1021
|
+
uid: z11.string().min(1),
|
|
1022
|
+
// Stores mounted on this machine (from global config).
|
|
1023
|
+
mountedStores: z11.array(
|
|
1024
|
+
z11.object({
|
|
1025
|
+
store_uuid: z11.string().min(1),
|
|
1026
|
+
alias: z11.string().min(1),
|
|
1027
|
+
remote: z11.string().min(1).optional(),
|
|
1028
|
+
writable: z11.boolean().default(true),
|
|
1029
|
+
// Marks the implicit personal store.
|
|
1030
|
+
personal: z11.boolean().default(false)
|
|
1031
|
+
}).strict()
|
|
1032
|
+
),
|
|
1033
|
+
// The project's declared required_stores (ids/aliases + optional remote).
|
|
1034
|
+
requiredStores: z11.array(
|
|
1035
|
+
z11.object({
|
|
1036
|
+
id: z11.string().min(1),
|
|
1037
|
+
suggested_remote: z11.string().min(1).optional()
|
|
1038
|
+
}).strict()
|
|
1039
|
+
),
|
|
1040
|
+
// Alias selected as the active write store for non-personal scopes, if any.
|
|
1041
|
+
activeWriteAlias: z11.string().min(1).optional()
|
|
1042
|
+
}).strict();
|
|
1043
|
+
var projectRootGoldenCaseSchema = z11.object({
|
|
1044
|
+
name: z11.string().min(1),
|
|
1045
|
+
note: z11.string().optional(),
|
|
1046
|
+
signals: projectRootSignalsSchema,
|
|
1047
|
+
// null expected = resolver should return no root for these signals.
|
|
1048
|
+
expected: projectRootResolutionSchema.nullable()
|
|
1049
|
+
}).strict();
|
|
1050
|
+
var projectRootGoldenFileSchema = z11.object({
|
|
1051
|
+
contract: z11.literal("project-root.golden"),
|
|
1052
|
+
cases: z11.array(projectRootGoldenCaseSchema).min(1)
|
|
1053
|
+
}).strict();
|
|
1054
|
+
var readSetGoldenCaseSchema = z11.object({
|
|
1055
|
+
name: z11.string().min(1),
|
|
1056
|
+
note: z11.string().optional(),
|
|
1057
|
+
input: storeResolveInputSchema,
|
|
1058
|
+
// Scope under test for the write-target expectation.
|
|
1059
|
+
writeScope: z11.string().min(1),
|
|
1060
|
+
expected: z11.object({
|
|
1061
|
+
readSet: storeReadSetSchema,
|
|
1062
|
+
writeTarget: writeTargetSchema.nullable(),
|
|
1063
|
+
writeWarnings: z11.array(storeResolverWarningSchema)
|
|
1064
|
+
}).strict()
|
|
1065
|
+
}).strict();
|
|
1066
|
+
var readSetGoldenFileSchema = z11.object({
|
|
1067
|
+
contract: z11.literal("read-set.golden"),
|
|
1068
|
+
cases: z11.array(readSetGoldenCaseSchema).min(1)
|
|
1069
|
+
}).strict();
|
|
1070
|
+
|
|
1071
|
+
// src/resolver/project-root-resolver.ts
|
|
1072
|
+
var ResolverNotImplementedError = class extends Error {
|
|
1073
|
+
constructor(what) {
|
|
1074
|
+
super(`${what} is not implemented yet (TDD target)`);
|
|
1075
|
+
this.name = "ResolverNotImplementedError";
|
|
1076
|
+
}
|
|
1077
|
+
};
|
|
1078
|
+
function createProjectRootResolver() {
|
|
1079
|
+
return {
|
|
1080
|
+
resolve(signals) {
|
|
1081
|
+
const projectId = signals.discoveredProjectId ?? null;
|
|
1082
|
+
if (signals.env !== void 0) {
|
|
1083
|
+
return { projectRoot: signals.env, projectId, signalUsed: "env" };
|
|
1084
|
+
}
|
|
1085
|
+
if (signals.markerDir !== void 0) {
|
|
1086
|
+
return {
|
|
1087
|
+
projectRoot: signals.markerDir,
|
|
1088
|
+
projectId,
|
|
1089
|
+
signalUsed: signals.markerDir === signals.cwd ? "cwd" : "marker"
|
|
1090
|
+
};
|
|
1091
|
+
}
|
|
1092
|
+
if (signals.repoRoot !== void 0) {
|
|
1093
|
+
return { projectRoot: signals.repoRoot, projectId, signalUsed: "repo" };
|
|
1094
|
+
}
|
|
1095
|
+
return null;
|
|
1096
|
+
}
|
|
1097
|
+
};
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
// src/resolver/store-resolver.ts
|
|
1101
|
+
function findPersonal(input) {
|
|
1102
|
+
return input.mountedStores.find((s) => s.personal);
|
|
1103
|
+
}
|
|
1104
|
+
function personalEntry(input) {
|
|
1105
|
+
const p = findPersonal(input);
|
|
1106
|
+
if (p === void 0) {
|
|
1107
|
+
return void 0;
|
|
1108
|
+
}
|
|
1109
|
+
const entry = { store_uuid: p.store_uuid, alias: p.alias, writable: p.writable };
|
|
1110
|
+
if (p.remote !== void 0) {
|
|
1111
|
+
entry.remote = p.remote;
|
|
1112
|
+
}
|
|
1113
|
+
return entry;
|
|
1114
|
+
}
|
|
1115
|
+
function createStoreResolver() {
|
|
1116
|
+
return {
|
|
1117
|
+
resolveReadSet(input) {
|
|
1118
|
+
const stores = [];
|
|
1119
|
+
const warnings = [];
|
|
1120
|
+
for (const req of input.requiredStores) {
|
|
1121
|
+
const matched = input.mountedStores.find(
|
|
1122
|
+
(m) => !m.personal && (m.alias === req.id || m.store_uuid === req.id)
|
|
1123
|
+
);
|
|
1124
|
+
if (matched === void 0) {
|
|
1125
|
+
const suffix = req.suggested_remote === void 0 ? "" : ` (suggested remote: ${req.suggested_remote})`;
|
|
1126
|
+
warnings.push({
|
|
1127
|
+
code: "missing_store",
|
|
1128
|
+
ref: req.id,
|
|
1129
|
+
message: `required store '${req.id}' is not mounted; run \`fabric store add\`${suffix}`
|
|
1130
|
+
});
|
|
1131
|
+
continue;
|
|
1132
|
+
}
|
|
1133
|
+
const entry = {
|
|
1134
|
+
store_uuid: matched.store_uuid,
|
|
1135
|
+
alias: matched.alias,
|
|
1136
|
+
writable: matched.writable
|
|
1137
|
+
};
|
|
1138
|
+
if (matched.remote !== void 0) {
|
|
1139
|
+
entry.remote = matched.remote;
|
|
1140
|
+
} else {
|
|
1141
|
+
warnings.push({
|
|
1142
|
+
code: "local_only_no_remote",
|
|
1143
|
+
ref: matched.alias,
|
|
1144
|
+
message: `store '${matched.alias}' is local-only; add a git remote to back it up (\`fabric store ... \` / doctor nudge)`
|
|
1145
|
+
});
|
|
1146
|
+
}
|
|
1147
|
+
stores.push(entry);
|
|
1148
|
+
}
|
|
1149
|
+
const personal = personalEntry(input);
|
|
1150
|
+
if (personal !== void 0) {
|
|
1151
|
+
stores.push(personal);
|
|
1152
|
+
}
|
|
1153
|
+
return { stores, warnings };
|
|
1154
|
+
},
|
|
1155
|
+
resolveWriteTarget(input, scope) {
|
|
1156
|
+
if (isPersonalScope(scope)) {
|
|
1157
|
+
const p = findPersonal(input);
|
|
1158
|
+
if (p === void 0) {
|
|
1159
|
+
return {
|
|
1160
|
+
target: null,
|
|
1161
|
+
warnings: [
|
|
1162
|
+
{
|
|
1163
|
+
code: "missing_store",
|
|
1164
|
+
ref: "personal",
|
|
1165
|
+
message: "no personal store is mounted; run `fabric install --global` first"
|
|
1166
|
+
}
|
|
1167
|
+
]
|
|
1168
|
+
};
|
|
1169
|
+
}
|
|
1170
|
+
return { target: { store_uuid: p.store_uuid, alias: p.alias }, warnings: [] };
|
|
1171
|
+
}
|
|
1172
|
+
const active = input.activeWriteAlias === void 0 ? void 0 : input.mountedStores.find((m) => m.writable && m.alias === input.activeWriteAlias);
|
|
1173
|
+
if (active === void 0) {
|
|
1174
|
+
return {
|
|
1175
|
+
target: null,
|
|
1176
|
+
warnings: [
|
|
1177
|
+
{
|
|
1178
|
+
code: "alias_unresolved",
|
|
1179
|
+
ref: input.activeWriteAlias ?? scope,
|
|
1180
|
+
message: `no writable store for scope '${scope}'; set an active write store with \`fabric store switch-write\``
|
|
1181
|
+
}
|
|
1182
|
+
]
|
|
1183
|
+
};
|
|
1184
|
+
}
|
|
1185
|
+
return { target: { store_uuid: active.store_uuid, alias: active.alias }, warnings: [] };
|
|
1186
|
+
},
|
|
1187
|
+
aliasToUuid(input, alias) {
|
|
1188
|
+
return input.mountedStores.find((m) => m.alias === alias)?.store_uuid;
|
|
1189
|
+
}
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
// src/resolver/store-disk-reader.ts
|
|
1194
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "fs";
|
|
1195
|
+
import { join } from "path";
|
|
1196
|
+
function readStoreIdentity(absDir) {
|
|
1197
|
+
const identityFile = join(absDir, STORE_LAYOUT.identityFile);
|
|
1198
|
+
if (!existsSync(identityFile)) {
|
|
1199
|
+
return null;
|
|
1200
|
+
}
|
|
1201
|
+
let raw;
|
|
1202
|
+
try {
|
|
1203
|
+
raw = JSON.parse(readFileSync(identityFile, "utf8"));
|
|
1204
|
+
} catch {
|
|
1205
|
+
return null;
|
|
1206
|
+
}
|
|
1207
|
+
const parsed = storeIdentitySchema.safeParse(raw);
|
|
1208
|
+
return parsed.success ? parsed.data : null;
|
|
1209
|
+
}
|
|
1210
|
+
function recognizeStoreDir(absDir) {
|
|
1211
|
+
return readStoreIdentity(absDir) !== null;
|
|
1212
|
+
}
|
|
1213
|
+
var SCRIPT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
1214
|
+
".cjs",
|
|
1215
|
+
".mjs",
|
|
1216
|
+
".js",
|
|
1217
|
+
".ts",
|
|
1218
|
+
".sh",
|
|
1219
|
+
".bash",
|
|
1220
|
+
".zsh",
|
|
1221
|
+
".py",
|
|
1222
|
+
".rb",
|
|
1223
|
+
".pl"
|
|
1224
|
+
]);
|
|
1225
|
+
function hasScriptExtension(name) {
|
|
1226
|
+
const dot = name.lastIndexOf(".");
|
|
1227
|
+
return dot !== -1 && SCRIPT_EXTENSIONS.has(name.slice(dot).toLowerCase());
|
|
1228
|
+
}
|
|
1229
|
+
function findStoreExecutableViolations(absDir) {
|
|
1230
|
+
const violations = [];
|
|
1231
|
+
const walk = (dir, rel) => {
|
|
1232
|
+
let entries;
|
|
1233
|
+
try {
|
|
1234
|
+
entries = readdirSync(dir);
|
|
1235
|
+
} catch {
|
|
1236
|
+
return;
|
|
1237
|
+
}
|
|
1238
|
+
for (const entry of entries) {
|
|
1239
|
+
if (rel === "" && entry === ".git") {
|
|
1240
|
+
continue;
|
|
1241
|
+
}
|
|
1242
|
+
const abs = join(dir, entry);
|
|
1243
|
+
const relPath = rel === "" ? entry : `${rel}/${entry}`;
|
|
1244
|
+
let stat;
|
|
1245
|
+
try {
|
|
1246
|
+
stat = statSync(abs);
|
|
1247
|
+
} catch {
|
|
1248
|
+
continue;
|
|
1249
|
+
}
|
|
1250
|
+
if (stat.isDirectory()) {
|
|
1251
|
+
walk(abs, relPath);
|
|
1252
|
+
continue;
|
|
1253
|
+
}
|
|
1254
|
+
if ((stat.mode & 73) !== 0 || hasScriptExtension(entry)) {
|
|
1255
|
+
violations.push(relPath);
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
};
|
|
1259
|
+
walk(absDir, "");
|
|
1260
|
+
return violations;
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
// src/resolver/store-qualified-id.ts
|
|
1264
|
+
var LOCAL_ID = /^K[PT]-(MOD|DEC|GLD|PIT|PRO)-\d{4,}$/u;
|
|
1265
|
+
function splitRef(ref) {
|
|
1266
|
+
const localMatch = ref.match(/K[PT]-(?:MOD|DEC|GLD|PIT|PRO)-\d{4,}$/u);
|
|
1267
|
+
if (localMatch === null) {
|
|
1268
|
+
return null;
|
|
1269
|
+
}
|
|
1270
|
+
const localId = localMatch[0];
|
|
1271
|
+
if (localId === ref) {
|
|
1272
|
+
return { storeQualifier: null, localId };
|
|
1273
|
+
}
|
|
1274
|
+
const head = ref.slice(0, ref.length - localId.length);
|
|
1275
|
+
if (!head.endsWith(":")) {
|
|
1276
|
+
return null;
|
|
1277
|
+
}
|
|
1278
|
+
return { storeQualifier: head.slice(0, -1), localId };
|
|
1279
|
+
}
|
|
1280
|
+
function resolveStoreQualifiedId(ref, candidates) {
|
|
1281
|
+
const split = splitRef(ref);
|
|
1282
|
+
if (split === null || !LOCAL_ID.test(split.localId)) {
|
|
1283
|
+
return { resolved: null, ambiguous: false, matches: [] };
|
|
1284
|
+
}
|
|
1285
|
+
const { storeQualifier, localId } = split;
|
|
1286
|
+
if (storeQualifier !== null) {
|
|
1287
|
+
const match = candidates.find(
|
|
1288
|
+
(c) => c.local_id === localId && (c.alias === storeQualifier || c.store_uuid === storeQualifier)
|
|
1289
|
+
);
|
|
1290
|
+
return match === void 0 ? { resolved: null, ambiguous: false, matches: [] } : { resolved: match, ambiguous: false, matches: [match] };
|
|
1291
|
+
}
|
|
1292
|
+
const matches = candidates.filter((c) => c.local_id === localId);
|
|
1293
|
+
if (matches.length === 1) {
|
|
1294
|
+
return { resolved: matches[0], ambiguous: false, matches };
|
|
1295
|
+
}
|
|
1296
|
+
return { resolved: null, ambiguous: matches.length > 1, matches };
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
// src/resolver/resolution.ts
|
|
1300
|
+
function specificity(scope) {
|
|
1301
|
+
return scope.split(":").length;
|
|
1302
|
+
}
|
|
1303
|
+
function resolveCandidates(candidates, options = {}) {
|
|
1304
|
+
const storeOrder = options.storeOrder ?? [];
|
|
1305
|
+
const storeRank = (uuid) => {
|
|
1306
|
+
const idx = storeOrder.indexOf(uuid);
|
|
1307
|
+
return idx === -1 ? storeOrder.length : idx;
|
|
1308
|
+
};
|
|
1309
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1310
|
+
const deduped = [];
|
|
1311
|
+
for (const c of candidates) {
|
|
1312
|
+
if (seen.has(c.global_ref)) {
|
|
1313
|
+
continue;
|
|
1314
|
+
}
|
|
1315
|
+
seen.add(c.global_ref);
|
|
1316
|
+
deduped.push(c);
|
|
1317
|
+
}
|
|
1318
|
+
const byLocal = /* @__PURE__ */ new Map();
|
|
1319
|
+
for (const c of deduped) {
|
|
1320
|
+
const stores = byLocal.get(c.local_id) ?? /* @__PURE__ */ new Set();
|
|
1321
|
+
stores.add(c.store_uuid);
|
|
1322
|
+
byLocal.set(c.local_id, stores);
|
|
1323
|
+
}
|
|
1324
|
+
const warnings = [];
|
|
1325
|
+
for (const [localId, stores] of byLocal) {
|
|
1326
|
+
if (stores.size > 1) {
|
|
1327
|
+
warnings.push({
|
|
1328
|
+
code: "shadowed_local_id",
|
|
1329
|
+
ref: localId,
|
|
1330
|
+
message: `local id '${localId}' exists in ${stores.size} stores; references must be store-qualified`
|
|
1331
|
+
});
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
for (const uuid of options.unavailableRequiredStores ?? []) {
|
|
1335
|
+
warnings.push({
|
|
1336
|
+
code: "required_store_unavailable",
|
|
1337
|
+
ref: uuid,
|
|
1338
|
+
message: `required store '${uuid}' is unavailable; results may be incomplete (not silently degraded)`
|
|
1339
|
+
});
|
|
1340
|
+
}
|
|
1341
|
+
const sorted = [...deduped].sort((a, b) => {
|
|
1342
|
+
const specDiff = specificity(b.semantic_scope) - specificity(a.semantic_scope);
|
|
1343
|
+
if (specDiff !== 0) {
|
|
1344
|
+
return specDiff;
|
|
1345
|
+
}
|
|
1346
|
+
const rankDiff = storeRank(a.store_uuid) - storeRank(b.store_uuid);
|
|
1347
|
+
if (rankDiff !== 0) {
|
|
1348
|
+
return rankDiff;
|
|
1349
|
+
}
|
|
1350
|
+
return a.global_ref < b.global_ref ? -1 : a.global_ref > b.global_ref ? 1 : 0;
|
|
1351
|
+
});
|
|
1352
|
+
const resolved = sorted.map((c, i) => ({
|
|
1353
|
+
...c,
|
|
1354
|
+
rank: i,
|
|
1355
|
+
reason: `scope '${scopeRoot(c.semantic_scope)}' (specificity ${specificity(
|
|
1356
|
+
c.semantic_scope
|
|
1357
|
+
)}), store '${c.alias}' (priority ${storeRank(c.store_uuid)})`
|
|
1358
|
+
}));
|
|
1359
|
+
return { resolved, warnings };
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
// src/store/core.ts
|
|
1363
|
+
import { execFileSync } from "child_process";
|
|
1364
|
+
import { existsSync as existsSync2, mkdirSync, readdirSync as readdirSync2, writeFileSync } from "fs";
|
|
1365
|
+
import { join as join2 } from "path";
|
|
1366
|
+
var STORE_PENDING_DIR = "pending";
|
|
1367
|
+
var STORE_GITIGNORE = [
|
|
1368
|
+
"# v2.1 store \u2014 volatile / derived data is never committed",
|
|
1369
|
+
"state/",
|
|
1370
|
+
"agents.meta.json",
|
|
1371
|
+
".cache/",
|
|
1372
|
+
""
|
|
1373
|
+
].join("\n");
|
|
1374
|
+
function git(cwd, args) {
|
|
1375
|
+
execFileSync("git", args, { cwd, stdio: ["ignore", "ignore", "pipe"] });
|
|
1376
|
+
}
|
|
1377
|
+
function initStore(absDir, identity, options = {}) {
|
|
1378
|
+
const parsed = storeIdentitySchema.parse(identity);
|
|
1379
|
+
const identityFile = join2(absDir, STORE_LAYOUT.identityFile);
|
|
1380
|
+
if (existsSync2(identityFile)) {
|
|
1381
|
+
throw new Error(`store already initialized at ${absDir} (store.json exists)`);
|
|
1382
|
+
}
|
|
1383
|
+
for (const type of STORE_KNOWLEDGE_TYPE_DIRS) {
|
|
1384
|
+
mkdirSync(join2(absDir, STORE_LAYOUT.knowledgeDir, type), { recursive: true });
|
|
1385
|
+
}
|
|
1386
|
+
mkdirSync(join2(absDir, STORE_LAYOUT.knowledgeDir, STORE_PENDING_DIR), { recursive: true });
|
|
1387
|
+
mkdirSync(join2(absDir, STORE_LAYOUT.bindingsDir), { recursive: true });
|
|
1388
|
+
mkdirSync(join2(absDir, STORE_LAYOUT.stateDir), { recursive: true });
|
|
1389
|
+
writeFileSync(identityFile, `${JSON.stringify(parsed, null, 2)}
|
|
1390
|
+
`, "utf8");
|
|
1391
|
+
writeFileSync(join2(absDir, ".gitignore"), STORE_GITIGNORE, "utf8");
|
|
1392
|
+
if (options.git !== false) {
|
|
1393
|
+
git(absDir, ["init", "-b", "main"]);
|
|
1394
|
+
}
|
|
1395
|
+
const readBack = readStoreIdentity(absDir);
|
|
1396
|
+
if (readBack === null) {
|
|
1397
|
+
throw new Error(`store init wrote an unrecognizable store.json at ${absDir}`);
|
|
1398
|
+
}
|
|
1399
|
+
return readBack;
|
|
1400
|
+
}
|
|
1401
|
+
function listMarkdown(dir) {
|
|
1402
|
+
if (!existsSync2(dir)) {
|
|
1403
|
+
return [];
|
|
1404
|
+
}
|
|
1405
|
+
return readdirSync2(dir).filter((name) => name.endsWith(".md")).sort().map((name) => join2(dir, name));
|
|
1406
|
+
}
|
|
1407
|
+
function listStoreKnowledge(store) {
|
|
1408
|
+
const refs = [];
|
|
1409
|
+
for (const type of STORE_KNOWLEDGE_TYPE_DIRS) {
|
|
1410
|
+
for (const file of listMarkdown(join2(store.dir, STORE_LAYOUT.knowledgeDir, type))) {
|
|
1411
|
+
refs.push({ store_uuid: store.store_uuid, alias: store.alias, type, file });
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
return refs;
|
|
1415
|
+
}
|
|
1416
|
+
function readKnowledgeAcrossStores(stores) {
|
|
1417
|
+
return stores.flatMap((store) => listStoreKnowledge(store));
|
|
1418
|
+
}
|
|
1419
|
+
function aggregatePendingAcrossStores(stores) {
|
|
1420
|
+
return stores.flatMap(
|
|
1421
|
+
(store) => listMarkdown(join2(store.dir, STORE_LAYOUT.knowledgeDir, STORE_PENDING_DIR)).map((file) => ({
|
|
1422
|
+
store_uuid: store.store_uuid,
|
|
1423
|
+
alias: store.alias,
|
|
1424
|
+
type: STORE_PENDING_DIR,
|
|
1425
|
+
file
|
|
1426
|
+
}))
|
|
1427
|
+
);
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
// src/store/secret-scan.ts
|
|
1431
|
+
var SECRET_RULES = [
|
|
1432
|
+
{ rule: "aws-access-key-id", re: /\bAKIA[0-9A-Z]{16}\b/ },
|
|
1433
|
+
{ rule: "private-key-block", re: /-----BEGIN (?:RSA |EC |OPENSSH |DSA |PGP )?PRIVATE KEY-----/ },
|
|
1434
|
+
{ rule: "openai-api-key", re: /\bsk-[A-Za-z0-9]{20,}\b/ },
|
|
1435
|
+
{ rule: "github-token", re: /\bgh[pousr]_[A-Za-z0-9]{20,}\b/ },
|
|
1436
|
+
{ rule: "slack-token", re: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/ },
|
|
1437
|
+
{
|
|
1438
|
+
rule: "credential-assignment",
|
|
1439
|
+
re: /(?:password|passwd|secret|api[_-]?key|access[_-]?token|token)\s*[:=]\s*['"][^'"\s]{8,}['"]/i
|
|
1440
|
+
}
|
|
1441
|
+
];
|
|
1442
|
+
function scanForSecrets(content) {
|
|
1443
|
+
const findings = [];
|
|
1444
|
+
const lines = content.split(/\r?\n/u);
|
|
1445
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1446
|
+
for (const { rule, re } of SECRET_RULES) {
|
|
1447
|
+
if (re.test(lines[i])) {
|
|
1448
|
+
findings.push({ rule, line: i + 1 });
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
return findings;
|
|
1453
|
+
}
|
|
1454
|
+
function hasSecrets(content) {
|
|
1455
|
+
return scanForSecrets(content).length > 0;
|
|
1456
|
+
}
|
|
1457
|
+
var REDACTION_PLACEHOLDER_PREFIX = "[REDACTED:";
|
|
1458
|
+
function redactSecrets(content) {
|
|
1459
|
+
let out = content;
|
|
1460
|
+
for (const { rule, re } of SECRET_RULES) {
|
|
1461
|
+
const flags = re.flags.includes("i") ? "gi" : "g";
|
|
1462
|
+
out = out.replace(new RegExp(re.source, flags), `${REDACTION_PLACEHOLDER_PREFIX}${rule}]`);
|
|
1463
|
+
}
|
|
1464
|
+
return out;
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
// src/store/cross-store-lint.ts
|
|
1468
|
+
function lintCrossStoreReferences(input) {
|
|
1469
|
+
if (input.entryVisibility !== "shared") {
|
|
1470
|
+
return [];
|
|
1471
|
+
}
|
|
1472
|
+
const violations = [];
|
|
1473
|
+
for (const ref of input.referencedGlobalRefs) {
|
|
1474
|
+
const parsed = parseGlobalRef(ref);
|
|
1475
|
+
if (parsed === null) {
|
|
1476
|
+
continue;
|
|
1477
|
+
}
|
|
1478
|
+
if (input.storeVisibility[parsed.store_uuid] === "personal") {
|
|
1479
|
+
violations.push({
|
|
1480
|
+
code: "personal-ref-in-shared",
|
|
1481
|
+
ref,
|
|
1482
|
+
to_store_uuid: parsed.store_uuid,
|
|
1483
|
+
message: `shared-store entry references personal-store id '${ref}' \u2014 personal knowledge must not leak into a shared store`
|
|
1484
|
+
});
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
return violations;
|
|
1488
|
+
}
|
|
1489
|
+
function isPersonalLeakIntoSharedStore(entryLayer, storeVisibility) {
|
|
1490
|
+
return entryLayer === "personal" && storeVisibility === "shared";
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
// src/store/observability.ts
|
|
1494
|
+
function redactValue(value) {
|
|
1495
|
+
return typeof value === "string" ? redactSecrets(value) : value;
|
|
1496
|
+
}
|
|
1497
|
+
function buildFailureTrace(stage, error, context = {}, code) {
|
|
1498
|
+
const rawMessage = error instanceof Error ? error.message : typeof error === "string" ? error : String(error);
|
|
1499
|
+
const derivedCode = code ?? (error instanceof Error && error.name ? error.name : "error");
|
|
1500
|
+
const redactedContext = {};
|
|
1501
|
+
for (const [key, value] of Object.entries(context)) {
|
|
1502
|
+
redactedContext[key] = redactValue(value);
|
|
1503
|
+
}
|
|
1504
|
+
return {
|
|
1505
|
+
stage,
|
|
1506
|
+
code: derivedCode,
|
|
1507
|
+
message: redactSecrets(rawMessage),
|
|
1508
|
+
context: redactedContext
|
|
1509
|
+
};
|
|
1510
|
+
}
|
|
1511
|
+
function buildDebugBundle(input) {
|
|
1512
|
+
const redactDeep = (value) => {
|
|
1513
|
+
if (typeof value === "string") {
|
|
1514
|
+
return redactSecrets(value);
|
|
1515
|
+
}
|
|
1516
|
+
if (Array.isArray(value)) {
|
|
1517
|
+
return value.map(redactDeep);
|
|
1518
|
+
}
|
|
1519
|
+
if (value !== null && typeof value === "object") {
|
|
1520
|
+
const out = {};
|
|
1521
|
+
for (const [k, v] of Object.entries(value)) {
|
|
1522
|
+
out[k] = redactDeep(v);
|
|
1523
|
+
}
|
|
1524
|
+
return out;
|
|
1525
|
+
}
|
|
1526
|
+
return value;
|
|
1527
|
+
};
|
|
1528
|
+
return {
|
|
1529
|
+
version: 1,
|
|
1530
|
+
config: redactDeep(input.config),
|
|
1531
|
+
diagnostics: redactDeep(input.diagnostics) ?? [],
|
|
1532
|
+
events: input.includeEvents === true ? (input.events ?? []).map(redactSecrets) : [],
|
|
1533
|
+
redacted: true
|
|
1534
|
+
};
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
// src/schemas/provenance.ts
|
|
1538
|
+
import { z as z12 } from "zod";
|
|
1539
|
+
var knowledgeProvenanceSchema = z12.object({
|
|
1540
|
+
store_uuid: storeUuidSchema,
|
|
1541
|
+
alias: z12.string().min(1),
|
|
1542
|
+
local_id: localKnowledgeIdSchema,
|
|
1543
|
+
global_ref: globalRefSchema,
|
|
1544
|
+
// Optional scope coordinate of the entry (resolution axis); present when the
|
|
1545
|
+
// surfacing tool has read the entry's frontmatter.
|
|
1546
|
+
semantic_scope: scopeCoordinateSchema.optional()
|
|
1547
|
+
}).strict();
|
|
1548
|
+
|
|
1549
|
+
// src/schemas/mcp-store-contracts.ts
|
|
1550
|
+
import { z as z13 } from "zod";
|
|
1551
|
+
var MCP_STORE_AWARE_TOOLS = [
|
|
1552
|
+
"fab_recall",
|
|
1553
|
+
"fab_plan_context",
|
|
1554
|
+
"fab_get_knowledge_sections",
|
|
1555
|
+
"fab_archive_scan",
|
|
1556
|
+
"fab_extract_knowledge",
|
|
1557
|
+
"fab_review"
|
|
1558
|
+
];
|
|
1559
|
+
var storeAwareEntrySchema = z13.object({
|
|
1560
|
+
stable_id: z13.string(),
|
|
1561
|
+
global_ref: globalRefSchema,
|
|
1562
|
+
provenance: knowledgeProvenanceSchema
|
|
1563
|
+
}).strict();
|
|
1564
|
+
var writtenToStoreSchema = z13.object({
|
|
1565
|
+
store_uuid: storeUuidSchema,
|
|
1566
|
+
alias: z13.string().min(1)
|
|
1567
|
+
}).strict();
|
|
1568
|
+
var MCP_STORE_AWARE_CONTRACTS = {
|
|
1569
|
+
fab_recall: { tool: "fab_recall", surfacesEntries: true, echoesWrittenStore: false },
|
|
1570
|
+
fab_plan_context: { tool: "fab_plan_context", surfacesEntries: true, echoesWrittenStore: false },
|
|
1571
|
+
fab_get_knowledge_sections: {
|
|
1572
|
+
tool: "fab_get_knowledge_sections",
|
|
1573
|
+
surfacesEntries: true,
|
|
1574
|
+
echoesWrittenStore: false
|
|
1575
|
+
},
|
|
1576
|
+
fab_archive_scan: {
|
|
1577
|
+
tool: "fab_archive_scan",
|
|
1578
|
+
surfacesEntries: false,
|
|
1579
|
+
echoesWrittenStore: true
|
|
1580
|
+
},
|
|
1581
|
+
fab_extract_knowledge: {
|
|
1582
|
+
tool: "fab_extract_knowledge",
|
|
1583
|
+
surfacesEntries: false,
|
|
1584
|
+
echoesWrittenStore: true
|
|
1585
|
+
},
|
|
1586
|
+
fab_review: { tool: "fab_review", surfacesEntries: true, echoesWrittenStore: true }
|
|
1587
|
+
};
|
|
1588
|
+
|
|
1589
|
+
// src/schemas/bindings-snapshot.ts
|
|
1590
|
+
import { z as z14 } from "zod";
|
|
1591
|
+
var resolvedBindingsSnapshotSchema = z14.object({
|
|
1592
|
+
// Schema version of the snapshot document.
|
|
1593
|
+
version: z14.literal(1),
|
|
1594
|
+
// The project this snapshot is bound to (S13).
|
|
1595
|
+
project_id: z14.string().min(1),
|
|
1596
|
+
// ISO-8601 generation timestamp (provenance / staleness signal for doctor).
|
|
1597
|
+
generated_at: z14.string().min(1),
|
|
1598
|
+
// Pre-resolved read-set (required_stores ∪ implicit personal + warnings).
|
|
1599
|
+
read_set: storeReadSetSchema,
|
|
1600
|
+
// Pre-resolved active write target for non-personal scopes (null if none).
|
|
1601
|
+
write_target: writeTargetSchema.nullable()
|
|
1602
|
+
}).strict();
|
|
1603
|
+
|
|
1604
|
+
// src/store/bindings.ts
|
|
1605
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
1606
|
+
import { join as join3 } from "path";
|
|
1607
|
+
function bindingsSnapshotPath(globalRoot, projectId) {
|
|
1608
|
+
return join3(globalRoot, GLOBAL_STATE_DIR, GLOBAL_BINDINGS_DIR, `${projectId}_resolved.json`);
|
|
1609
|
+
}
|
|
1610
|
+
function writeBindingsSnapshot(options) {
|
|
1611
|
+
const resolver = createStoreResolver();
|
|
1612
|
+
const read_set = resolver.resolveReadSet(options.resolveInput);
|
|
1613
|
+
const { target } = resolver.resolveWriteTarget(options.resolveInput, options.writeScope);
|
|
1614
|
+
const snapshot = resolvedBindingsSnapshotSchema.parse({
|
|
1615
|
+
version: 1,
|
|
1616
|
+
project_id: options.projectId,
|
|
1617
|
+
generated_at: options.now,
|
|
1618
|
+
read_set,
|
|
1619
|
+
write_target: target
|
|
1620
|
+
});
|
|
1621
|
+
const path = bindingsSnapshotPath(options.globalRoot, options.projectId);
|
|
1622
|
+
mkdirSync2(join3(path, ".."), { recursive: true });
|
|
1623
|
+
writeFileSync2(path, `${JSON.stringify(snapshot, null, 2)}
|
|
1624
|
+
`, "utf8");
|
|
1625
|
+
return snapshot;
|
|
1626
|
+
}
|
|
1627
|
+
function readBindingsSnapshot(globalRoot, projectId) {
|
|
1628
|
+
const path = bindingsSnapshotPath(globalRoot, projectId);
|
|
1629
|
+
if (!existsSync3(path)) {
|
|
1630
|
+
return null;
|
|
1631
|
+
}
|
|
1632
|
+
try {
|
|
1633
|
+
const parsed = resolvedBindingsSnapshotSchema.safeParse(JSON.parse(readFileSync2(path, "utf8")));
|
|
1634
|
+
return parsed.success ? parsed.data : null;
|
|
1635
|
+
} catch {
|
|
1636
|
+
return null;
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
// src/store/store-lifecycle.ts
|
|
1641
|
+
function findMountedStore(config, aliasOrUuid) {
|
|
1642
|
+
return config.stores.find((s) => s.alias === aliasOrUuid || s.store_uuid === aliasOrUuid);
|
|
1643
|
+
}
|
|
1644
|
+
function addMountedStore(config, store) {
|
|
1645
|
+
const aliasClash = config.stores.find(
|
|
1646
|
+
(s) => s.alias === store.alias && s.store_uuid !== store.store_uuid
|
|
1647
|
+
);
|
|
1648
|
+
if (aliasClash !== void 0) {
|
|
1649
|
+
throw new Error(
|
|
1650
|
+
`alias '${store.alias}' already mounts store ${aliasClash.store_uuid}; choose another alias`
|
|
1651
|
+
);
|
|
1652
|
+
}
|
|
1653
|
+
const existing = config.stores.find((s) => s.store_uuid === store.store_uuid);
|
|
1654
|
+
const stores = existing === void 0 ? [...config.stores, store] : config.stores.map((s) => s.store_uuid === store.store_uuid ? store : s);
|
|
1655
|
+
return { ...config, stores };
|
|
1656
|
+
}
|
|
1657
|
+
function detachMountedStore(config, alias) {
|
|
1658
|
+
const detached = config.stores.find((s) => s.alias === alias) ?? null;
|
|
1659
|
+
if (detached === null) {
|
|
1660
|
+
return { config, detached: null };
|
|
1661
|
+
}
|
|
1662
|
+
return {
|
|
1663
|
+
config: { ...config, stores: config.stores.filter((s) => s.alias !== alias) },
|
|
1664
|
+
detached
|
|
1665
|
+
};
|
|
1666
|
+
}
|
|
1667
|
+
function bindRequiredStore(required, entry) {
|
|
1668
|
+
return required.some((r) => r.id === entry.id) ? required.map((r) => r.id === entry.id ? entry : r) : [...required, entry];
|
|
1669
|
+
}
|
|
1670
|
+
function explainStore(config, alias) {
|
|
1671
|
+
const store = findMountedStore(config, alias);
|
|
1672
|
+
if (store === void 0) {
|
|
1673
|
+
return null;
|
|
1674
|
+
}
|
|
1675
|
+
return {
|
|
1676
|
+
alias: store.alias,
|
|
1677
|
+
store_uuid: store.store_uuid,
|
|
1678
|
+
remote: store.remote ?? null,
|
|
1679
|
+
local_only: store.remote === void 0
|
|
1680
|
+
};
|
|
1681
|
+
}
|
|
1682
|
+
|
|
377
1683
|
// src/schemas/forensic-report.ts
|
|
378
|
-
import { z as
|
|
379
|
-
var forensicCodeSampleSchema =
|
|
380
|
-
path:
|
|
381
|
-
lines:
|
|
382
|
-
snippet:
|
|
383
|
-
pattern_hint:
|
|
384
|
-
});
|
|
385
|
-
var forensicEvidenceAnchorSchema =
|
|
386
|
-
file:
|
|
387
|
-
line:
|
|
388
|
-
snippet:
|
|
389
|
-
});
|
|
390
|
-
var forensicAssertionCoverageSchema =
|
|
391
|
-
ratio:
|
|
392
|
-
total:
|
|
393
|
-
matched:
|
|
394
|
-
co_occurring_patterns:
|
|
395
|
-
});
|
|
396
|
-
var forensicAssertionSchema =
|
|
397
|
-
type:
|
|
398
|
-
statement:
|
|
399
|
-
confidence:
|
|
400
|
-
evidence:
|
|
1684
|
+
import { z as z15 } from "zod";
|
|
1685
|
+
var forensicCodeSampleSchema = z15.object({
|
|
1686
|
+
path: z15.string(),
|
|
1687
|
+
lines: z15.string(),
|
|
1688
|
+
snippet: z15.string(),
|
|
1689
|
+
pattern_hint: z15.string()
|
|
1690
|
+
});
|
|
1691
|
+
var forensicEvidenceAnchorSchema = z15.object({
|
|
1692
|
+
file: z15.string(),
|
|
1693
|
+
line: z15.string(),
|
|
1694
|
+
snippet: z15.string()
|
|
1695
|
+
});
|
|
1696
|
+
var forensicAssertionCoverageSchema = z15.object({
|
|
1697
|
+
ratio: z15.number().min(0).max(1),
|
|
1698
|
+
total: z15.number().int().nonnegative(),
|
|
1699
|
+
matched: z15.number().int().nonnegative(),
|
|
1700
|
+
co_occurring_patterns: z15.array(z15.string())
|
|
1701
|
+
});
|
|
1702
|
+
var forensicAssertionSchema = z15.object({
|
|
1703
|
+
type: z15.enum(["framework", "pattern", "invariant", "domain"]),
|
|
1704
|
+
statement: z15.string(),
|
|
1705
|
+
confidence: z15.enum(["HIGH", "MEDIUM", "LOW"]),
|
|
1706
|
+
evidence: z15.array(forensicEvidenceAnchorSchema),
|
|
401
1707
|
coverage: forensicAssertionCoverageSchema,
|
|
402
|
-
proposed_rule:
|
|
403
|
-
alternatives:
|
|
404
|
-
});
|
|
405
|
-
var forensicTopologySchema =
|
|
406
|
-
total_files:
|
|
407
|
-
by_ext:
|
|
408
|
-
key_dirs:
|
|
409
|
-
max_depth:
|
|
410
|
-
});
|
|
411
|
-
var forensicEntryPointSchema =
|
|
412
|
-
path:
|
|
413
|
-
reason:
|
|
414
|
-
size_bytes:
|
|
415
|
-
});
|
|
416
|
-
var forensicFrameworkSchema =
|
|
417
|
-
kind:
|
|
418
|
-
version:
|
|
419
|
-
subkind:
|
|
420
|
-
evidence:
|
|
421
|
-
});
|
|
422
|
-
var forensicReadmeSchema =
|
|
423
|
-
quality:
|
|
424
|
-
line_count:
|
|
425
|
-
has_contributing:
|
|
426
|
-
});
|
|
427
|
-
var candidateFileEntrySchema =
|
|
428
|
-
path:
|
|
429
|
-
family:
|
|
430
|
-
rationale:
|
|
431
|
-
});
|
|
432
|
-
var forensicSamplingBudgetSchema =
|
|
433
|
-
max_files:
|
|
434
|
-
max_lines_per_file:
|
|
435
|
-
});
|
|
436
|
-
var forensicReportSchema =
|
|
437
|
-
version:
|
|
438
|
-
generated_at:
|
|
439
|
-
generated_by:
|
|
440
|
-
target:
|
|
441
|
-
project_name:
|
|
1708
|
+
proposed_rule: z15.string().optional(),
|
|
1709
|
+
alternatives: z15.array(z15.string()).optional()
|
|
1710
|
+
});
|
|
1711
|
+
var forensicTopologySchema = z15.object({
|
|
1712
|
+
total_files: z15.number().int().nonnegative(),
|
|
1713
|
+
by_ext: z15.record(z15.number().int().nonnegative()),
|
|
1714
|
+
key_dirs: z15.array(z15.string()),
|
|
1715
|
+
max_depth: z15.number().int().nonnegative()
|
|
1716
|
+
});
|
|
1717
|
+
var forensicEntryPointSchema = z15.object({
|
|
1718
|
+
path: z15.string(),
|
|
1719
|
+
reason: z15.string(),
|
|
1720
|
+
size_bytes: z15.number().int().nonnegative().optional()
|
|
1721
|
+
});
|
|
1722
|
+
var forensicFrameworkSchema = z15.object({
|
|
1723
|
+
kind: z15.string(),
|
|
1724
|
+
version: z15.string(),
|
|
1725
|
+
subkind: z15.string(),
|
|
1726
|
+
evidence: z15.array(z15.string())
|
|
1727
|
+
});
|
|
1728
|
+
var forensicReadmeSchema = z15.object({
|
|
1729
|
+
quality: z15.enum(["missing", "stub", "ok"]),
|
|
1730
|
+
line_count: z15.number().int().nonnegative(),
|
|
1731
|
+
has_contributing: z15.boolean()
|
|
1732
|
+
});
|
|
1733
|
+
var candidateFileEntrySchema = z15.object({
|
|
1734
|
+
path: z15.string(),
|
|
1735
|
+
family: z15.enum(["entry", "component", "config", "test", "domain"]),
|
|
1736
|
+
rationale: z15.string()
|
|
1737
|
+
});
|
|
1738
|
+
var forensicSamplingBudgetSchema = z15.object({
|
|
1739
|
+
max_files: z15.literal(15),
|
|
1740
|
+
max_lines_per_file: z15.literal(100)
|
|
1741
|
+
});
|
|
1742
|
+
var forensicReportSchema = z15.object({
|
|
1743
|
+
version: z15.string(),
|
|
1744
|
+
generated_at: z15.string(),
|
|
1745
|
+
generated_by: z15.string(),
|
|
1746
|
+
target: z15.string(),
|
|
1747
|
+
project_name: z15.string(),
|
|
442
1748
|
framework: forensicFrameworkSchema,
|
|
443
1749
|
topology: forensicTopologySchema,
|
|
444
|
-
entry_points:
|
|
445
|
-
code_samples:
|
|
446
|
-
assertions:
|
|
447
|
-
candidate_files:
|
|
1750
|
+
entry_points: z15.array(forensicEntryPointSchema),
|
|
1751
|
+
code_samples: z15.array(forensicCodeSampleSchema),
|
|
1752
|
+
assertions: z15.array(forensicAssertionSchema),
|
|
1753
|
+
candidate_files: z15.array(candidateFileEntrySchema),
|
|
448
1754
|
sampling_budget: forensicSamplingBudgetSchema,
|
|
449
1755
|
readme: forensicReadmeSchema,
|
|
450
|
-
recommendations_for_skill:
|
|
1756
|
+
recommendations_for_skill: z15.array(z15.string()).optional()
|
|
451
1757
|
});
|
|
452
1758
|
|
|
453
1759
|
// src/schemas/init-context.ts
|
|
454
|
-
import { z as
|
|
455
|
-
var initContextFrameworkSchema =
|
|
456
|
-
kind:
|
|
457
|
-
version:
|
|
458
|
-
subkind:
|
|
459
|
-
});
|
|
460
|
-
var initContextInvariantConfidenceSnapshotSchema =
|
|
461
|
-
confidence:
|
|
462
|
-
evidence_refs:
|
|
463
|
-
});
|
|
464
|
-
var initContextSourceEvidenceSchema =
|
|
465
|
-
file:
|
|
466
|
-
lines:
|
|
467
|
-
});
|
|
468
|
-
var initContextInvariantSchema =
|
|
469
|
-
type:
|
|
470
|
-
rule:
|
|
471
|
-
rationale:
|
|
1760
|
+
import { z as z16 } from "zod";
|
|
1761
|
+
var initContextFrameworkSchema = z16.object({
|
|
1762
|
+
kind: z16.string(),
|
|
1763
|
+
version: z16.string(),
|
|
1764
|
+
subkind: z16.string()
|
|
1765
|
+
});
|
|
1766
|
+
var initContextInvariantConfidenceSnapshotSchema = z16.object({
|
|
1767
|
+
confidence: z16.enum(["HIGH", "MEDIUM", "LOW"]),
|
|
1768
|
+
evidence_refs: z16.array(z16.string())
|
|
1769
|
+
});
|
|
1770
|
+
var initContextSourceEvidenceSchema = z16.object({
|
|
1771
|
+
file: z16.string(),
|
|
1772
|
+
lines: z16.string()
|
|
1773
|
+
});
|
|
1774
|
+
var initContextInvariantSchema = z16.object({
|
|
1775
|
+
type: z16.enum(["ban", "require", "protect"]),
|
|
1776
|
+
rule: z16.string(),
|
|
1777
|
+
rationale: z16.string().optional(),
|
|
472
1778
|
confidence_snapshot: initContextInvariantConfidenceSnapshotSchema.optional(),
|
|
473
|
-
source_evidence:
|
|
474
|
-
});
|
|
475
|
-
var initContextDomainGroupSchema =
|
|
476
|
-
name:
|
|
477
|
-
paths:
|
|
478
|
-
summary:
|
|
479
|
-
topology_type:
|
|
480
|
-
target_path:
|
|
481
|
-
});
|
|
482
|
-
var initContextInterviewTrailEntrySchema =
|
|
483
|
-
phase:
|
|
484
|
-
question:
|
|
485
|
-
answer:
|
|
486
|
-
presentation:
|
|
487
|
-
user_corrections:
|
|
488
|
-
});
|
|
489
|
-
var initContextSchema =
|
|
1779
|
+
source_evidence: z16.array(initContextSourceEvidenceSchema).optional()
|
|
1780
|
+
});
|
|
1781
|
+
var initContextDomainGroupSchema = z16.object({
|
|
1782
|
+
name: z16.string(),
|
|
1783
|
+
paths: z16.array(z16.string()),
|
|
1784
|
+
summary: z16.string().optional(),
|
|
1785
|
+
topology_type: z16.enum(["mirror", "cross-cutting"]).optional(),
|
|
1786
|
+
target_path: z16.string().optional()
|
|
1787
|
+
});
|
|
1788
|
+
var initContextInterviewTrailEntrySchema = z16.object({
|
|
1789
|
+
phase: z16.string(),
|
|
1790
|
+
question: z16.string(),
|
|
1791
|
+
answer: z16.string(),
|
|
1792
|
+
presentation: z16.string().optional(),
|
|
1793
|
+
user_corrections: z16.array(z16.string()).optional()
|
|
1794
|
+
});
|
|
1795
|
+
var initContextSchema = z16.object({
|
|
490
1796
|
framework: initContextFrameworkSchema,
|
|
491
|
-
architecture_patterns:
|
|
492
|
-
invariants:
|
|
493
|
-
domain_groups:
|
|
494
|
-
interview_trail:
|
|
495
|
-
forensic_ref:
|
|
1797
|
+
architecture_patterns: z16.array(z16.string()),
|
|
1798
|
+
invariants: z16.array(initContextInvariantSchema),
|
|
1799
|
+
domain_groups: z16.array(initContextDomainGroupSchema),
|
|
1800
|
+
interview_trail: z16.array(initContextInterviewTrailEntrySchema),
|
|
1801
|
+
forensic_ref: z16.string()
|
|
496
1802
|
});
|
|
497
1803
|
|
|
498
1804
|
// src/schemas/events.ts
|
|
499
|
-
import { z as
|
|
500
|
-
var metaUpdatedEventSchema =
|
|
501
|
-
type:
|
|
1805
|
+
import { z as z17 } from "zod";
|
|
1806
|
+
var metaUpdatedEventSchema = z17.object({
|
|
1807
|
+
type: z17.literal("meta:updated"),
|
|
502
1808
|
payload: agentsMetaSchema
|
|
503
1809
|
});
|
|
504
|
-
var lockDriftEventSchema =
|
|
505
|
-
type:
|
|
506
|
-
payload:
|
|
507
|
-
locked:
|
|
508
|
-
drifted:
|
|
1810
|
+
var lockDriftEventSchema = z17.object({
|
|
1811
|
+
type: z17.literal("lock:drift"),
|
|
1812
|
+
payload: z17.object({
|
|
1813
|
+
locked: z17.array(humanLockEntrySchema),
|
|
1814
|
+
drifted: z17.array(humanLockEntrySchema)
|
|
509
1815
|
})
|
|
510
1816
|
});
|
|
511
|
-
var lockApprovedEventSchema =
|
|
512
|
-
type:
|
|
513
|
-
payload:
|
|
514
|
-
locked:
|
|
515
|
-
approved:
|
|
1817
|
+
var lockApprovedEventSchema = z17.object({
|
|
1818
|
+
type: z17.literal("lock:approved"),
|
|
1819
|
+
payload: z17.object({
|
|
1820
|
+
locked: z17.array(humanLockEntrySchema),
|
|
1821
|
+
approved: z17.array(humanLockEntrySchema)
|
|
516
1822
|
})
|
|
517
1823
|
});
|
|
518
|
-
var ledgerAppendedEventSchema =
|
|
519
|
-
type:
|
|
1824
|
+
var ledgerAppendedEventSchema = z17.object({
|
|
1825
|
+
type: z17.literal("ledger:appended"),
|
|
520
1826
|
payload: ledgerEntrySchema
|
|
521
1827
|
});
|
|
522
|
-
var driftDetectedEventSchema =
|
|
523
|
-
type:
|
|
1828
|
+
var driftDetectedEventSchema = z17.object({
|
|
1829
|
+
type: z17.literal("drift:detected"),
|
|
524
1830
|
payload: forensicReportSchema
|
|
525
1831
|
});
|
|
526
|
-
var fabricEventSchema =
|
|
1832
|
+
var fabricEventSchema = z17.discriminatedUnion("type", [
|
|
527
1833
|
metaUpdatedEventSchema,
|
|
528
1834
|
lockDriftEventSchema,
|
|
529
1835
|
lockApprovedEventSchema,
|
|
@@ -532,271 +1838,541 @@ var fabricEventSchema = z8.discriminatedUnion("type", [
|
|
|
532
1838
|
]);
|
|
533
1839
|
|
|
534
1840
|
// src/schemas/event-ledger.ts
|
|
535
|
-
import { z as
|
|
1841
|
+
import { z as z18 } from "zod";
|
|
1842
|
+
|
|
1843
|
+
// src/cite-line-parser.ts
|
|
1844
|
+
var ID_RE = /^K[TP]-[A-Z]+-\d+$/;
|
|
1845
|
+
var SENTINEL_RE = /^KB:\s*none\b\s*(?:\[[^\]]*\])?\s*$/i;
|
|
1846
|
+
var QUALIFIED_ID = String.raw`(?:[^\s,:]+:)?K[TP]-[A-Z]+-\d+`;
|
|
1847
|
+
var FULL_RE = new RegExp(
|
|
1848
|
+
String.raw`^KB:\s+(${QUALIFIED_ID}(?:\s*,\s*${QUALIFIED_ID})*)(?:\s+\(([^)]*)\))?(?:\s+\[([^\]]+)\])?(?:\s+→\s*(.+))?\s*$`
|
|
1849
|
+
);
|
|
1850
|
+
function splitStorePrefix(token) {
|
|
1851
|
+
const colon = token.lastIndexOf(":");
|
|
1852
|
+
return colon === -1 ? { store: null, id: token } : { store: token.slice(0, colon), id: token.slice(colon + 1) };
|
|
1853
|
+
}
|
|
1854
|
+
var CHAINED_FROM_ID_RE = /chained-from\s+(K[TP]-[A-Z]+-\d+)/i;
|
|
1855
|
+
var LEGACY_CITE_TAG_REMAP = {
|
|
1856
|
+
planned: "applied",
|
|
1857
|
+
recalled: "applied",
|
|
1858
|
+
"chained-from": "applied"
|
|
1859
|
+
};
|
|
1860
|
+
function normalizeCiteTag(rawTag) {
|
|
1861
|
+
const head = rawTag.trim().split(/[\s:]+/)[0].toLowerCase();
|
|
1862
|
+
if (head === "applied" || head === "dismissed" || head === "none") {
|
|
1863
|
+
return head;
|
|
1864
|
+
}
|
|
1865
|
+
return LEGACY_CITE_TAG_REMAP[head] ?? "none";
|
|
1866
|
+
}
|
|
1867
|
+
function parseTag(rawTag) {
|
|
1868
|
+
if (!rawTag) return "none";
|
|
1869
|
+
return normalizeCiteTag(rawTag);
|
|
1870
|
+
}
|
|
1871
|
+
function parseContractTail(tail) {
|
|
1872
|
+
const result = { operators: [], skip_reason: null };
|
|
1873
|
+
if (!tail) return result;
|
|
1874
|
+
const tokens = tail.trim().split(/\s+/).filter((t) => t.length > 0);
|
|
1875
|
+
for (const token of tokens) {
|
|
1876
|
+
const skipMatch = token.match(/^skip:(.+)$/i);
|
|
1877
|
+
if (skipMatch) {
|
|
1878
|
+
if (result.skip_reason === null) result.skip_reason = skipMatch[1];
|
|
1879
|
+
continue;
|
|
1880
|
+
}
|
|
1881
|
+
const notEditMatch = token.match(/^!edit:(.+)$/i);
|
|
1882
|
+
if (notEditMatch) {
|
|
1883
|
+
result.operators.push({ kind: "not_edit", target: notEditMatch[1] });
|
|
1884
|
+
continue;
|
|
1885
|
+
}
|
|
1886
|
+
const opMatch = token.match(/^(edit|require|forbid):(.+)$/i);
|
|
1887
|
+
if (opMatch) {
|
|
1888
|
+
result.operators.push({
|
|
1889
|
+
kind: opMatch[1].toLowerCase(),
|
|
1890
|
+
target: opMatch[2]
|
|
1891
|
+
});
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1894
|
+
return result;
|
|
1895
|
+
}
|
|
1896
|
+
function parseLine(line) {
|
|
1897
|
+
const trimmed = line.trim();
|
|
1898
|
+
if (trimmed.length === 0) return null;
|
|
1899
|
+
if (SENTINEL_RE.test(trimmed)) {
|
|
1900
|
+
return { ids: [], stores: [], tag: "none", commitment: null };
|
|
1901
|
+
}
|
|
1902
|
+
const fullMatch = trimmed.match(FULL_RE);
|
|
1903
|
+
if (fullMatch) {
|
|
1904
|
+
const split = fullMatch[1].split(",").map((part) => part.trim()).filter((part) => part.length > 0).map(splitStorePrefix);
|
|
1905
|
+
if (split.some((entry) => !ID_RE.test(entry.id))) return null;
|
|
1906
|
+
const primaryIds = split.map((entry) => entry.id);
|
|
1907
|
+
const primaryStores = split.map((entry) => entry.store);
|
|
1908
|
+
const rawTag = fullMatch[3];
|
|
1909
|
+
const tag = parseTag(rawTag);
|
|
1910
|
+
const chainedIds = [];
|
|
1911
|
+
if (rawTag !== void 0) {
|
|
1912
|
+
const chained = CHAINED_FROM_ID_RE.exec(rawTag);
|
|
1913
|
+
if (chained !== null && ID_RE.test(chained[1])) {
|
|
1914
|
+
chainedIds.push(chained[1]);
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
return {
|
|
1918
|
+
ids: [...primaryIds, ...chainedIds],
|
|
1919
|
+
// chained-from ids are never store-qualified → null per chained id.
|
|
1920
|
+
stores: [...primaryStores, ...chainedIds.map(() => null)],
|
|
1921
|
+
tag,
|
|
1922
|
+
commitment: parseContractTail(fullMatch[4])
|
|
1923
|
+
};
|
|
1924
|
+
}
|
|
1925
|
+
return null;
|
|
1926
|
+
}
|
|
1927
|
+
function parseCiteLine(raw) {
|
|
1928
|
+
const result = {
|
|
1929
|
+
cite_ids: [],
|
|
1930
|
+
cite_tags: [],
|
|
1931
|
+
cite_commitments: [],
|
|
1932
|
+
cite_stores: []
|
|
1933
|
+
};
|
|
1934
|
+
if (typeof raw !== "string") return result;
|
|
1935
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
1936
|
+
const parsed = parseLine(line);
|
|
1937
|
+
if (!parsed) continue;
|
|
1938
|
+
result.cite_tags.push(parsed.tag);
|
|
1939
|
+
for (let i = 0; i < parsed.ids.length; i += 1) {
|
|
1940
|
+
result.cite_ids.push(parsed.ids[i]);
|
|
1941
|
+
result.cite_stores.push(parsed.stores[i] ?? null);
|
|
1942
|
+
}
|
|
1943
|
+
if (parsed.commitment !== null) {
|
|
1944
|
+
for (let i = 0; i < parsed.ids.length; i += 1) {
|
|
1945
|
+
result.cite_commitments.push(parsed.commitment);
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
return result;
|
|
1950
|
+
}
|
|
1951
|
+
|
|
1952
|
+
// src/schemas/event-ledger.ts
|
|
1953
|
+
var citeTagSchema = z18.preprocess(
|
|
1954
|
+
(value) => typeof value === "string" ? normalizeCiteTag(value) : value,
|
|
1955
|
+
z18.enum(["applied", "dismissed", "none"])
|
|
1956
|
+
);
|
|
536
1957
|
var eventLedgerEnvelopeSchema = {
|
|
537
|
-
kind:
|
|
538
|
-
id:
|
|
539
|
-
ts:
|
|
540
|
-
schema_version:
|
|
541
|
-
correlation_id:
|
|
542
|
-
session_id:
|
|
1958
|
+
kind: z18.literal("fabric-event"),
|
|
1959
|
+
id: z18.string(),
|
|
1960
|
+
ts: z18.number().int().nonnegative(),
|
|
1961
|
+
schema_version: z18.literal(1),
|
|
1962
|
+
correlation_id: z18.string().optional(),
|
|
1963
|
+
session_id: z18.string().optional()
|
|
543
1964
|
};
|
|
544
|
-
var stringRecordSchema =
|
|
545
|
-
var knowledgeContextPlannedEventSchema =
|
|
546
|
-
...eventLedgerEnvelopeSchema,
|
|
547
|
-
event_type:
|
|
548
|
-
target_paths:
|
|
549
|
-
required_stable_ids:
|
|
550
|
-
ai_selectable_stable_ids:
|
|
551
|
-
final_stable_ids:
|
|
552
|
-
selection_token:
|
|
553
|
-
client_hash:
|
|
554
|
-
intent:
|
|
555
|
-
known_tech:
|
|
556
|
-
diagnostics:
|
|
557
|
-
});
|
|
558
|
-
var knowledgeSelectionEventSchema =
|
|
559
|
-
...eventLedgerEnvelopeSchema,
|
|
560
|
-
event_type:
|
|
561
|
-
selection_token:
|
|
562
|
-
target_paths:
|
|
563
|
-
required_stable_ids:
|
|
564
|
-
ai_selectable_stable_ids:
|
|
565
|
-
ai_selected_stable_ids:
|
|
566
|
-
final_stable_ids:
|
|
1965
|
+
var stringRecordSchema = z18.record(z18.string());
|
|
1966
|
+
var knowledgeContextPlannedEventSchema = z18.object({
|
|
1967
|
+
...eventLedgerEnvelopeSchema,
|
|
1968
|
+
event_type: z18.literal("knowledge_context_planned"),
|
|
1969
|
+
target_paths: z18.array(z18.string()),
|
|
1970
|
+
required_stable_ids: z18.array(z18.string()),
|
|
1971
|
+
ai_selectable_stable_ids: z18.array(z18.string()),
|
|
1972
|
+
final_stable_ids: z18.array(z18.string()),
|
|
1973
|
+
selection_token: z18.string().optional(),
|
|
1974
|
+
client_hash: z18.string().optional(),
|
|
1975
|
+
intent: z18.string().optional(),
|
|
1976
|
+
known_tech: z18.array(z18.string()).optional(),
|
|
1977
|
+
diagnostics: z18.array(z18.unknown()).optional()
|
|
1978
|
+
});
|
|
1979
|
+
var knowledgeSelectionEventSchema = z18.object({
|
|
1980
|
+
...eventLedgerEnvelopeSchema,
|
|
1981
|
+
event_type: z18.literal("knowledge_selection"),
|
|
1982
|
+
selection_token: z18.string(),
|
|
1983
|
+
target_paths: z18.array(z18.string()),
|
|
1984
|
+
required_stable_ids: z18.array(z18.string()),
|
|
1985
|
+
ai_selectable_stable_ids: z18.array(z18.string()),
|
|
1986
|
+
ai_selected_stable_ids: z18.array(z18.string()),
|
|
1987
|
+
final_stable_ids: z18.array(z18.string()),
|
|
567
1988
|
ai_selection_reasons: stringRecordSchema,
|
|
568
|
-
rejected_stable_ids:
|
|
569
|
-
ignored_stable_ids:
|
|
570
|
-
});
|
|
571
|
-
var knowledgeSectionsFetchedEventSchema =
|
|
572
|
-
...eventLedgerEnvelopeSchema,
|
|
573
|
-
event_type:
|
|
574
|
-
selection_token:
|
|
575
|
-
target_paths:
|
|
576
|
-
requested_sections:
|
|
577
|
-
final_stable_ids:
|
|
578
|
-
ai_selected_stable_ids:
|
|
579
|
-
diagnostics:
|
|
580
|
-
});
|
|
581
|
-
var editIntentCheckedEventSchema =
|
|
582
|
-
...eventLedgerEnvelopeSchema,
|
|
583
|
-
event_type:
|
|
584
|
-
path:
|
|
585
|
-
compliant:
|
|
586
|
-
intent:
|
|
587
|
-
ledger_entry_id:
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
1989
|
+
rejected_stable_ids: z18.array(z18.string()),
|
|
1990
|
+
ignored_stable_ids: z18.array(z18.string())
|
|
1991
|
+
});
|
|
1992
|
+
var knowledgeSectionsFetchedEventSchema = z18.object({
|
|
1993
|
+
...eventLedgerEnvelopeSchema,
|
|
1994
|
+
event_type: z18.literal("knowledge_sections_fetched"),
|
|
1995
|
+
selection_token: z18.string(),
|
|
1996
|
+
target_paths: z18.array(z18.string()).optional(),
|
|
1997
|
+
requested_sections: z18.array(z18.string()),
|
|
1998
|
+
final_stable_ids: z18.array(z18.string()),
|
|
1999
|
+
ai_selected_stable_ids: z18.array(z18.string()),
|
|
2000
|
+
diagnostics: z18.array(z18.unknown()).optional()
|
|
2001
|
+
});
|
|
2002
|
+
var editIntentCheckedEventSchema = z18.object({
|
|
2003
|
+
...eventLedgerEnvelopeSchema,
|
|
2004
|
+
event_type: z18.literal("edit_intent_checked"),
|
|
2005
|
+
path: z18.string(),
|
|
2006
|
+
compliant: z18.boolean(),
|
|
2007
|
+
intent: z18.string(),
|
|
2008
|
+
ledger_entry_id: z18.string(),
|
|
2009
|
+
// rc.35 TASK-07 (P0-2): add "hook" — emitted by the PreToolUse narrow hook
|
|
2010
|
+
// for every Edit/Write/MultiEdit fire so cite-coverage doctor metrics see
|
|
2011
|
+
// actual edit signals (previously editsTouched was permanently 0 because
|
|
2012
|
+
// no production caller of appendLedgerEntry existed).
|
|
2013
|
+
ledger_source: z18.enum(["ai", "human", "hook"]).optional(),
|
|
2014
|
+
commit_sha: z18.string().optional(),
|
|
2015
|
+
parent_sha: z18.string().optional(),
|
|
2016
|
+
parent_ledger_entry_id: z18.string().optional(),
|
|
2017
|
+
diff_stat: z18.string().optional(),
|
|
2018
|
+
annotation: z18.string().optional(),
|
|
2019
|
+
matched_rule_context_ts: z18.number().int().nonnegative().nullable(),
|
|
2020
|
+
window_ms: z18.number().int().nonnegative()
|
|
2021
|
+
});
|
|
2022
|
+
var knowledgeDriftDetectedEventSchema = z18.object({
|
|
2023
|
+
...eventLedgerEnvelopeSchema,
|
|
2024
|
+
event_type: z18.literal("knowledge_drift_detected"),
|
|
2025
|
+
revision: z18.string().optional(),
|
|
2026
|
+
drifted_stable_ids: z18.array(z18.string()),
|
|
2027
|
+
missing_files: z18.array(z18.string()),
|
|
2028
|
+
stale_files: z18.array(z18.string()),
|
|
2029
|
+
details: z18.array(
|
|
2030
|
+
z18.object({
|
|
2031
|
+
file: z18.string(),
|
|
2032
|
+
stable_id: z18.string(),
|
|
2033
|
+
expected_hash: z18.string(),
|
|
2034
|
+
actual_hash: z18.string().nullable()
|
|
610
2035
|
})
|
|
611
2036
|
).optional()
|
|
612
2037
|
});
|
|
613
|
-
var mcpEventLedgerEventSchema =
|
|
2038
|
+
var mcpEventLedgerEventSchema = z18.object({
|
|
2039
|
+
...eventLedgerEnvelopeSchema,
|
|
2040
|
+
event_type: z18.literal("mcp_event"),
|
|
2041
|
+
mcp_event_id: z18.string(),
|
|
2042
|
+
stream_id: z18.string(),
|
|
2043
|
+
message: z18.unknown()
|
|
2044
|
+
});
|
|
2045
|
+
var reapplyCompletedEventSchema = z18.object({
|
|
2046
|
+
...eventLedgerEnvelopeSchema,
|
|
2047
|
+
event_type: z18.literal("reapply_completed"),
|
|
2048
|
+
preserved_ledger: z18.boolean(),
|
|
2049
|
+
preserved_meta: z18.boolean(),
|
|
2050
|
+
rules_count: z18.number().int().nonnegative()
|
|
2051
|
+
});
|
|
2052
|
+
var installDiffAppliedEventSchema = z18.object({
|
|
614
2053
|
...eventLedgerEnvelopeSchema,
|
|
615
|
-
event_type:
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
2054
|
+
event_type: z18.literal("install_diff_applied"),
|
|
2055
|
+
applied: z18.array(z18.string()),
|
|
2056
|
+
canonical: z18.array(z18.string()),
|
|
2057
|
+
drifted: z18.array(z18.string())
|
|
619
2058
|
});
|
|
620
|
-
var
|
|
2059
|
+
var eventLedgerTruncatedEventSchema = z18.object({
|
|
621
2060
|
...eventLedgerEnvelopeSchema,
|
|
622
|
-
event_type:
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
2061
|
+
event_type: z18.literal("event_ledger_truncated"),
|
|
2062
|
+
byte_offset: z18.number().int().nonnegative(),
|
|
2063
|
+
byte_length: z18.number().int().nonnegative(),
|
|
2064
|
+
corrupted_path: z18.string()
|
|
626
2065
|
});
|
|
627
|
-
var
|
|
2066
|
+
var mcpConfigMigratedEventSchema = z18.object({
|
|
628
2067
|
...eventLedgerEnvelopeSchema,
|
|
629
|
-
event_type:
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
corrupted_path: z9.string()
|
|
2068
|
+
event_type: z18.literal("mcp_config_migrated"),
|
|
2069
|
+
source: z18.literal("doctor_fix"),
|
|
2070
|
+
removed_from: z18.string()
|
|
633
2071
|
});
|
|
634
|
-
var
|
|
2072
|
+
var bootstrapMarkerMigratedEventSchema = z18.object({
|
|
635
2073
|
...eventLedgerEnvelopeSchema,
|
|
636
|
-
event_type:
|
|
637
|
-
|
|
638
|
-
|
|
2074
|
+
event_type: z18.literal("bootstrap_marker_migrated"),
|
|
2075
|
+
path: z18.string(),
|
|
2076
|
+
migrated_count: z18.number().int().nonnegative(),
|
|
2077
|
+
legacy_marker: z18.literal("fabric:knowledge-base"),
|
|
2078
|
+
new_marker: z18.literal("fabric:bootstrap"),
|
|
2079
|
+
timestamp: z18.string()
|
|
639
2080
|
});
|
|
640
|
-
var metaReconciledOnStartupEventSchema =
|
|
2081
|
+
var metaReconciledOnStartupEventSchema = z18.object({
|
|
641
2082
|
...eventLedgerEnvelopeSchema,
|
|
642
|
-
event_type:
|
|
643
|
-
reconciled_files:
|
|
644
|
-
duration_ms:
|
|
645
|
-
source:
|
|
2083
|
+
event_type: z18.literal("meta_reconciled_on_startup"),
|
|
2084
|
+
reconciled_files: z18.array(z18.string()),
|
|
2085
|
+
duration_ms: z18.number().int().nonnegative(),
|
|
2086
|
+
source: z18.literal("reconcileKnowledge")
|
|
646
2087
|
});
|
|
647
|
-
var metaReconciledEventSchema =
|
|
2088
|
+
var metaReconciledEventSchema = z18.object({
|
|
648
2089
|
...eventLedgerEnvelopeSchema,
|
|
649
|
-
event_type:
|
|
650
|
-
reconciled_files:
|
|
651
|
-
duration_ms:
|
|
652
|
-
|
|
653
|
-
|
|
2090
|
+
event_type: z18.literal("meta_reconciled"),
|
|
2091
|
+
reconciled_files: z18.array(z18.string()),
|
|
2092
|
+
duration_ms: z18.number().int().nonnegative(),
|
|
2093
|
+
// v2.0.0-rc.23 TASK-005 (a-B): added `auto-heal-description` trigger so the
|
|
2094
|
+
// read-path plan_context handler can drive a full reconcile when it detects
|
|
2095
|
+
// any node carrying `description === undefined` (legacy meta drift that the
|
|
2096
|
+
// revision-hash gate cannot catch — a missing description doesn't move the
|
|
2097
|
+
// revision). Symmetric to rc.22 D2 read-side auto-heal but covers the
|
|
2098
|
+
// description-undefined case which the revision drift gate misses.
|
|
2099
|
+
// v2.0.0-rc.27 TASK-001 (§2.9): `post-approve` / `post-modify` added so
|
|
2100
|
+
// `fab_review` write-actions can flush newly-promoted entries into
|
|
2101
|
+
// `agents.meta.json.nodes[id]` synchronously — without this the new entry
|
|
2102
|
+
// remains description-less until the next plan_context auto-heal.
|
|
2103
|
+
// v2.0.0-rc.29 TASK-005 (BUG-G1): `auto-heal-after-drift` added so
|
|
2104
|
+
// `ensureKnowledgeFresh` hot-path can chain a paired reconcile (closing the
|
|
2105
|
+
// drift→heal gap) when the caller opts in via `autoHealOnDrift: true`.
|
|
2106
|
+
trigger: z18.enum([
|
|
2107
|
+
"doctor",
|
|
2108
|
+
"manual",
|
|
2109
|
+
"auto-heal-description",
|
|
2110
|
+
"auto-heal-after-drift",
|
|
2111
|
+
"post-approve",
|
|
2112
|
+
"post-modify"
|
|
2113
|
+
]),
|
|
2114
|
+
source: z18.literal("reconcileKnowledge"),
|
|
2115
|
+
// v2.0.0-rc.22 TASK-014 (Scope E): set when reconcileKnowledge forced a
|
|
2116
|
+
// writeKnowledgeMeta on revision drift alone (no per-file content drift).
|
|
2117
|
+
// Distinguishes top-level schema/revision repair from the standard per-file
|
|
2118
|
+
// drift path. Optional so existing emitters stay unchanged.
|
|
2119
|
+
force_write_reason: z18.enum(["revision_drift"]).optional()
|
|
654
2120
|
});
|
|
655
|
-
var claudeSkillPathMigratedEventSchema =
|
|
2121
|
+
var claudeSkillPathMigratedEventSchema = z18.object({
|
|
656
2122
|
...eventLedgerEnvelopeSchema,
|
|
657
|
-
event_type:
|
|
658
|
-
from:
|
|
659
|
-
to:
|
|
2123
|
+
event_type: z18.literal("claude_skill_path_migrated"),
|
|
2124
|
+
from: z18.string(),
|
|
2125
|
+
to: z18.string()
|
|
660
2126
|
});
|
|
661
|
-
var claudeHookPathMigratedEventSchema =
|
|
2127
|
+
var claudeHookPathMigratedEventSchema = z18.object({
|
|
662
2128
|
...eventLedgerEnvelopeSchema,
|
|
663
|
-
event_type:
|
|
664
|
-
from:
|
|
665
|
-
to:
|
|
2129
|
+
event_type: z18.literal("claude_hook_path_migrated"),
|
|
2130
|
+
from: z18.string(),
|
|
2131
|
+
to: z18.string()
|
|
666
2132
|
});
|
|
667
|
-
var codexSkillPathMigratedEventSchema =
|
|
2133
|
+
var codexSkillPathMigratedEventSchema = z18.object({
|
|
668
2134
|
...eventLedgerEnvelopeSchema,
|
|
669
|
-
event_type:
|
|
670
|
-
from:
|
|
671
|
-
to:
|
|
2135
|
+
event_type: z18.literal("codex_skill_path_migrated"),
|
|
2136
|
+
from: z18.string(),
|
|
2137
|
+
to: z18.string()
|
|
672
2138
|
});
|
|
673
|
-
var initScanCompletedEventSchema =
|
|
2139
|
+
var initScanCompletedEventSchema = z18.object({
|
|
674
2140
|
...eventLedgerEnvelopeSchema,
|
|
675
|
-
event_type:
|
|
676
|
-
written_stable_ids:
|
|
677
|
-
duration_ms:
|
|
678
|
-
source:
|
|
2141
|
+
event_type: z18.literal("init_scan_completed"),
|
|
2142
|
+
written_stable_ids: z18.array(z18.string()),
|
|
2143
|
+
duration_ms: z18.number().int().nonnegative(),
|
|
2144
|
+
source: z18.enum(["init", "scan", "doctor_fix", "doctor-rescan"]).optional()
|
|
679
2145
|
});
|
|
680
|
-
var knowledgeProposedEventSchema =
|
|
2146
|
+
var knowledgeProposedEventSchema = z18.object({
|
|
681
2147
|
...eventLedgerEnvelopeSchema,
|
|
682
|
-
event_type:
|
|
683
|
-
stable_id:
|
|
684
|
-
timestamp:
|
|
685
|
-
reason:
|
|
2148
|
+
event_type: z18.literal("knowledge_proposed"),
|
|
2149
|
+
stable_id: z18.string().optional(),
|
|
2150
|
+
timestamp: z18.string().datetime(),
|
|
2151
|
+
reason: z18.string().optional()
|
|
686
2152
|
});
|
|
687
|
-
var knowledgePromoteStartedEventSchema =
|
|
2153
|
+
var knowledgePromoteStartedEventSchema = z18.object({
|
|
688
2154
|
...eventLedgerEnvelopeSchema,
|
|
689
|
-
event_type:
|
|
690
|
-
stable_id:
|
|
691
|
-
timestamp:
|
|
692
|
-
reason:
|
|
2155
|
+
event_type: z18.literal("knowledge_promote_started"),
|
|
2156
|
+
stable_id: z18.string().optional(),
|
|
2157
|
+
timestamp: z18.string().datetime(),
|
|
2158
|
+
reason: z18.string().optional()
|
|
693
2159
|
});
|
|
694
|
-
var knowledgePromotedEventSchema =
|
|
2160
|
+
var knowledgePromotedEventSchema = z18.object({
|
|
695
2161
|
...eventLedgerEnvelopeSchema,
|
|
696
|
-
event_type:
|
|
697
|
-
stable_id:
|
|
698
|
-
timestamp:
|
|
699
|
-
reason:
|
|
2162
|
+
event_type: z18.literal("knowledge_promoted"),
|
|
2163
|
+
stable_id: z18.string().optional(),
|
|
2164
|
+
timestamp: z18.string().datetime(),
|
|
2165
|
+
reason: z18.string().optional()
|
|
700
2166
|
});
|
|
701
|
-
var knowledgePromoteFailedEventSchema =
|
|
2167
|
+
var knowledgePromoteFailedEventSchema = z18.object({
|
|
702
2168
|
...eventLedgerEnvelopeSchema,
|
|
703
|
-
event_type:
|
|
704
|
-
stable_id:
|
|
705
|
-
timestamp:
|
|
706
|
-
reason:
|
|
2169
|
+
event_type: z18.literal("knowledge_promote_failed"),
|
|
2170
|
+
stable_id: z18.string().optional(),
|
|
2171
|
+
timestamp: z18.string().datetime(),
|
|
2172
|
+
reason: z18.string()
|
|
707
2173
|
});
|
|
708
|
-
var knowledgeLayerChangedEventSchema =
|
|
2174
|
+
var knowledgeLayerChangedEventSchema = z18.object({
|
|
709
2175
|
...eventLedgerEnvelopeSchema,
|
|
710
|
-
event_type:
|
|
711
|
-
stable_id:
|
|
712
|
-
timestamp:
|
|
713
|
-
reason:
|
|
714
|
-
from_layer:
|
|
715
|
-
to_layer:
|
|
2176
|
+
event_type: z18.literal("knowledge_layer_changed"),
|
|
2177
|
+
stable_id: z18.string().optional(),
|
|
2178
|
+
timestamp: z18.string().datetime(),
|
|
2179
|
+
reason: z18.string().optional(),
|
|
2180
|
+
from_layer: z18.enum(["team", "personal"]),
|
|
2181
|
+
to_layer: z18.enum(["team", "personal"]),
|
|
2182
|
+
// v2.0.0-rc.37 NEW-24: record the pre-flip stable_id so downstream consumers
|
|
2183
|
+
// (fab_plan_context redirect surface, fab_get_knowledge_sections.redirect_to)
|
|
2184
|
+
// can map a stale caller-held id back to the post-flip canonical id without
|
|
2185
|
+
// requiring the caller to re-issue plan-context. Optional for forward-
|
|
2186
|
+
// compatibility with rc ≤36 events that never carried this field.
|
|
2187
|
+
previous_stable_id: z18.string().optional()
|
|
716
2188
|
});
|
|
717
|
-
var
|
|
2189
|
+
var knowledgeIdRedirectEventSchema = z18.object({
|
|
718
2190
|
...eventLedgerEnvelopeSchema,
|
|
719
|
-
event_type:
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
to_slug: z9.string()
|
|
2191
|
+
event_type: z18.literal("knowledge_id_redirect"),
|
|
2192
|
+
timestamp: z18.string().datetime(),
|
|
2193
|
+
previous_stable_id: z18.string(),
|
|
2194
|
+
new_stable_id: z18.string(),
|
|
2195
|
+
reason: z18.string().optional()
|
|
725
2196
|
});
|
|
726
|
-
var
|
|
2197
|
+
var knowledgeSlugRenamedEventSchema = z18.object({
|
|
727
2198
|
...eventLedgerEnvelopeSchema,
|
|
728
|
-
event_type:
|
|
729
|
-
stable_id:
|
|
730
|
-
timestamp:
|
|
731
|
-
reason:
|
|
2199
|
+
event_type: z18.literal("knowledge_slug_renamed"),
|
|
2200
|
+
stable_id: z18.string().optional(),
|
|
2201
|
+
timestamp: z18.string().datetime(),
|
|
2202
|
+
reason: z18.string().optional(),
|
|
2203
|
+
from_slug: z18.string(),
|
|
2204
|
+
to_slug: z18.string()
|
|
732
2205
|
});
|
|
733
|
-
var
|
|
2206
|
+
var knowledgeDemotedEventSchema = z18.object({
|
|
734
2207
|
...eventLedgerEnvelopeSchema,
|
|
735
|
-
event_type:
|
|
736
|
-
stable_id:
|
|
737
|
-
timestamp:
|
|
738
|
-
reason:
|
|
2208
|
+
event_type: z18.literal("knowledge_demoted"),
|
|
2209
|
+
stable_id: z18.string().optional(),
|
|
2210
|
+
timestamp: z18.string().datetime(),
|
|
2211
|
+
reason: z18.string().optional()
|
|
739
2212
|
});
|
|
740
|
-
var
|
|
2213
|
+
var knowledgeArchivedEventSchema = z18.object({
|
|
741
2214
|
...eventLedgerEnvelopeSchema,
|
|
742
|
-
event_type:
|
|
743
|
-
stable_id:
|
|
744
|
-
timestamp:
|
|
745
|
-
reason:
|
|
2215
|
+
event_type: z18.literal("knowledge_archived"),
|
|
2216
|
+
stable_id: z18.string().optional(),
|
|
2217
|
+
timestamp: z18.string().datetime(),
|
|
2218
|
+
reason: z18.string().optional()
|
|
746
2219
|
});
|
|
747
|
-
var
|
|
2220
|
+
var knowledgeArchiveAttemptedEventSchema = z18.object({
|
|
748
2221
|
...eventLedgerEnvelopeSchema,
|
|
749
|
-
event_type:
|
|
750
|
-
stable_id:
|
|
751
|
-
timestamp:
|
|
752
|
-
reason:
|
|
753
|
-
until: z9.string().datetime().optional()
|
|
2222
|
+
event_type: z18.literal("knowledge_archive_attempted"),
|
|
2223
|
+
stable_id: z18.string().optional(),
|
|
2224
|
+
timestamp: z18.string().datetime(),
|
|
2225
|
+
reason: z18.string().optional()
|
|
754
2226
|
});
|
|
755
|
-
var
|
|
2227
|
+
var knowledgeUnarchivedEventSchema = z18.object({
|
|
756
2228
|
...eventLedgerEnvelopeSchema,
|
|
757
|
-
event_type:
|
|
758
|
-
stable_id:
|
|
759
|
-
timestamp:
|
|
760
|
-
reason:
|
|
2229
|
+
event_type: z18.literal("knowledge_unarchived"),
|
|
2230
|
+
stable_id: z18.string().optional(),
|
|
2231
|
+
timestamp: z18.string().datetime(),
|
|
2232
|
+
reason: z18.string().optional(),
|
|
2233
|
+
// Pre-move archive path (e.g. ".fabric/.archive/decisions/KT-D-0007--single-cjs-hook.md").
|
|
2234
|
+
archive_path: z18.string().optional(),
|
|
2235
|
+
// Post-move canonical path (e.g. ".fabric/knowledge/team/decisions/KT-D-0007--single-cjs-hook.md").
|
|
2236
|
+
restored_to: z18.string().optional()
|
|
761
2237
|
});
|
|
762
|
-
var
|
|
2238
|
+
var knowledgeDeferredEventSchema = z18.object({
|
|
763
2239
|
...eventLedgerEnvelopeSchema,
|
|
764
|
-
event_type:
|
|
765
|
-
stable_id:
|
|
766
|
-
|
|
767
|
-
|
|
2240
|
+
event_type: z18.literal("knowledge_deferred"),
|
|
2241
|
+
stable_id: z18.string().optional(),
|
|
2242
|
+
timestamp: z18.string().datetime(),
|
|
2243
|
+
reason: z18.string().optional(),
|
|
2244
|
+
until: z18.string().datetime().optional()
|
|
768
2245
|
});
|
|
769
|
-
var
|
|
2246
|
+
var knowledgeRejectedEventSchema = z18.object({
|
|
770
2247
|
...eventLedgerEnvelopeSchema,
|
|
771
|
-
event_type:
|
|
772
|
-
stable_id:
|
|
773
|
-
timestamp:
|
|
774
|
-
|
|
775
|
-
to_scope: z9.enum(["narrow", "broad"]),
|
|
776
|
-
reason: z9.string()
|
|
2248
|
+
event_type: z18.literal("knowledge_rejected"),
|
|
2249
|
+
stable_id: z18.string().optional(),
|
|
2250
|
+
timestamp: z18.string().datetime(),
|
|
2251
|
+
reason: z18.string()
|
|
777
2252
|
});
|
|
778
|
-
var
|
|
2253
|
+
var knowledgeConsumedEventSchema = z18.object({
|
|
779
2254
|
...eventLedgerEnvelopeSchema,
|
|
780
|
-
event_type:
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
timestamp: z9.string().datetime()
|
|
2255
|
+
event_type: z18.literal("knowledge_consumed"),
|
|
2256
|
+
stable_id: z18.string(),
|
|
2257
|
+
consumed_at: z18.string().datetime(),
|
|
2258
|
+
client_hash: z18.string()
|
|
785
2259
|
});
|
|
786
|
-
var
|
|
2260
|
+
var knowledgeScopeDegradedEventSchema = z18.object({
|
|
787
2261
|
...eventLedgerEnvelopeSchema,
|
|
788
|
-
event_type:
|
|
789
|
-
stable_id:
|
|
790
|
-
|
|
2262
|
+
event_type: z18.literal("knowledge_scope_degraded"),
|
|
2263
|
+
stable_id: z18.string(),
|
|
2264
|
+
timestamp: z18.string().datetime(),
|
|
2265
|
+
from_scope: z18.enum(["narrow", "broad"]),
|
|
2266
|
+
to_scope: z18.enum(["narrow", "broad"]),
|
|
2267
|
+
reason: z18.string()
|
|
791
2268
|
});
|
|
792
|
-
var
|
|
2269
|
+
var doctorRunEventSchema = z18.object({
|
|
793
2270
|
...eventLedgerEnvelopeSchema,
|
|
794
|
-
event_type:
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
2271
|
+
event_type: z18.literal("doctor_run"),
|
|
2272
|
+
mode: z18.enum(["lint", "fix-knowledge"]),
|
|
2273
|
+
issues: z18.number().int().nonnegative(),
|
|
2274
|
+
mutations: z18.number().int().nonnegative().optional(),
|
|
2275
|
+
timestamp: z18.string().datetime()
|
|
798
2276
|
});
|
|
799
|
-
var
|
|
2277
|
+
var knowledgePathDangledEventSchema = z18.object({
|
|
2278
|
+
...eventLedgerEnvelopeSchema,
|
|
2279
|
+
event_type: z18.literal("knowledge_path_dangled"),
|
|
2280
|
+
stable_id: z18.string(),
|
|
2281
|
+
removed_glob: z18.string()
|
|
2282
|
+
});
|
|
2283
|
+
var relevanceMigrationRunEventSchema = z18.object({
|
|
2284
|
+
...eventLedgerEnvelopeSchema,
|
|
2285
|
+
event_type: z18.literal("relevance_migration_run"),
|
|
2286
|
+
timestamp: z18.string().datetime(),
|
|
2287
|
+
scanned_count: z18.number().int().nonnegative(),
|
|
2288
|
+
touched_count: z18.number().int().nonnegative()
|
|
2289
|
+
});
|
|
2290
|
+
var pendingAutoArchivedEventSchema = z18.object({
|
|
2291
|
+
...eventLedgerEnvelopeSchema,
|
|
2292
|
+
event_type: z18.literal("pending_auto_archived"),
|
|
2293
|
+
pending_path: z18.string(),
|
|
2294
|
+
archived_to: z18.string(),
|
|
2295
|
+
reason: z18.string()
|
|
2296
|
+
});
|
|
2297
|
+
var assistantTurnObservedEventSchema = z18.object({
|
|
2298
|
+
...eventLedgerEnvelopeSchema,
|
|
2299
|
+
event_type: z18.literal("assistant_turn_observed"),
|
|
2300
|
+
kb_line_raw: z18.string().nullable(),
|
|
2301
|
+
cite_ids: z18.array(z18.string()).default([]),
|
|
2302
|
+
cite_tags: z18.array(citeTagSchema).default([]),
|
|
2303
|
+
// v2.0.0-rc.24 TASK-01: per-cite contract commitments. Index-aligned with
|
|
2304
|
+
// cite_ids/cite_tags (commitments[i] belongs to cite_ids[i]). Each slot
|
|
2305
|
+
// carries `operators[]` (kind + glob target) or `skip_reason` when the cite
|
|
2306
|
+
// cannot be operator-ized. Old rc.20-rc.23 events naturally parse with an
|
|
2307
|
+
// empty array via `.default([])` and are excluded from contract-policy
|
|
2308
|
+
// audits by the marker-gate (see cite_contract_policy_activated below).
|
|
2309
|
+
// Mirrors the rc.20 cite_tags parallel-array evolution exactly.
|
|
2310
|
+
cite_commitments: z18.array(
|
|
2311
|
+
z18.object({
|
|
2312
|
+
operators: z18.array(
|
|
2313
|
+
z18.object({
|
|
2314
|
+
kind: z18.enum(["edit", "not_edit", "require", "forbid"]),
|
|
2315
|
+
target: z18.string()
|
|
2316
|
+
})
|
|
2317
|
+
),
|
|
2318
|
+
skip_reason: z18.string().nullable()
|
|
2319
|
+
})
|
|
2320
|
+
).default([]),
|
|
2321
|
+
client: z18.enum(["cc", "codex", "cursor"]).optional(),
|
|
2322
|
+
turn_id: z18.string(),
|
|
2323
|
+
envelope_index: z18.number().int().nonnegative().optional(),
|
|
2324
|
+
timestamp: z18.string().datetime()
|
|
2325
|
+
});
|
|
2326
|
+
var citePolicyActivatedEventSchema = z18.object({
|
|
2327
|
+
...eventLedgerEnvelopeSchema,
|
|
2328
|
+
event_type: z18.literal("cite_policy_activated"),
|
|
2329
|
+
policy_version: z18.string(),
|
|
2330
|
+
timestamp: z18.string().datetime()
|
|
2331
|
+
});
|
|
2332
|
+
var citeContractPolicyActivatedEventSchema = z18.object({
|
|
2333
|
+
...eventLedgerEnvelopeSchema,
|
|
2334
|
+
event_type: z18.literal("cite_contract_policy_activated")
|
|
2335
|
+
});
|
|
2336
|
+
var eventsRotatedEventSchema = z18.object({
|
|
2337
|
+
...eventLedgerEnvelopeSchema,
|
|
2338
|
+
event_type: z18.literal("events_rotated"),
|
|
2339
|
+
cutoff_ts: z18.string().datetime(),
|
|
2340
|
+
archived_count: z18.number().int().nonnegative(),
|
|
2341
|
+
kept_count: z18.number().int().nonnegative(),
|
|
2342
|
+
archive_path: z18.string()
|
|
2343
|
+
});
|
|
2344
|
+
var knowledgeMetaAutoHealedEventSchema = z18.object({
|
|
2345
|
+
...eventLedgerEnvelopeSchema,
|
|
2346
|
+
event_type: z18.literal("knowledge_meta_auto_healed"),
|
|
2347
|
+
previous_revision_hash: z18.string(),
|
|
2348
|
+
revision_hash: z18.string(),
|
|
2349
|
+
trigger: z18.literal("read"),
|
|
2350
|
+
caller: z18.enum(["planContext", "getKnowledgeSections", "getKnowledge", "extractKnowledge"]).optional()
|
|
2351
|
+
});
|
|
2352
|
+
var serveLockClearedEventSchema = z18.object({
|
|
2353
|
+
...eventLedgerEnvelopeSchema,
|
|
2354
|
+
event_type: z18.literal("serve_lock_cleared"),
|
|
2355
|
+
pid: z18.number().int().nonnegative(),
|
|
2356
|
+
age_ms: z18.number().int().nonnegative(),
|
|
2357
|
+
timestamp: z18.string().datetime()
|
|
2358
|
+
});
|
|
2359
|
+
var knowledgeEnrichedEventSchema = z18.object({
|
|
2360
|
+
...eventLedgerEnvelopeSchema,
|
|
2361
|
+
event_type: z18.literal("knowledge_enriched"),
|
|
2362
|
+
path: z18.string(),
|
|
2363
|
+
added_fields: z18.array(z18.enum(["intent_clues", "tech_stack", "impact", "must_read_if"])),
|
|
2364
|
+
mode: z18.enum(["auto", "preview", "readonly", "interactive"]),
|
|
2365
|
+
timestamp: z18.string().datetime()
|
|
2366
|
+
});
|
|
2367
|
+
var sessionArchiveAttemptedEventSchema = z18.object({
|
|
2368
|
+
...eventLedgerEnvelopeSchema,
|
|
2369
|
+
event_type: z18.literal("session_archive_attempted"),
|
|
2370
|
+
outcome: z18.enum(["proposed", "viability_failed", "user_dismissed", "skipped_no_signal"]),
|
|
2371
|
+
covered_through_ts: z18.number().int().nonnegative(),
|
|
2372
|
+
candidates_proposed: z18.number().int().nonnegative().default(0),
|
|
2373
|
+
knowledge_proposed_ids: z18.array(z18.string()).default([])
|
|
2374
|
+
});
|
|
2375
|
+
var eventLedgerEventSchema = z18.discriminatedUnion("event_type", [
|
|
800
2376
|
knowledgeContextPlannedEventSchema,
|
|
801
2377
|
knowledgeSelectionEventSchema,
|
|
802
2378
|
knowledgeSectionsFetchedEventSchema,
|
|
@@ -804,8 +2380,12 @@ var eventLedgerEventSchema = z9.discriminatedUnion("event_type", [
|
|
|
804
2380
|
knowledgeDriftDetectedEventSchema,
|
|
805
2381
|
mcpEventLedgerEventSchema,
|
|
806
2382
|
reapplyCompletedEventSchema,
|
|
2383
|
+
installDiffAppliedEventSchema,
|
|
807
2384
|
eventLedgerTruncatedEventSchema,
|
|
808
2385
|
mcpConfigMigratedEventSchema,
|
|
2386
|
+
// v2.0.0-rc.19 TASK-004: bootstrap_marker_migrated — one-time fabric:knowledge-base
|
|
2387
|
+
// → fabric:bootstrap marker rewrite emitted per file by `fabric doctor --fix`.
|
|
2388
|
+
bootstrapMarkerMigratedEventSchema,
|
|
809
2389
|
metaReconciledOnStartupEventSchema,
|
|
810
2390
|
metaReconciledEventSchema,
|
|
811
2391
|
claudeSkillPathMigratedEventSchema,
|
|
@@ -818,10 +2398,14 @@ var eventLedgerEventSchema = z9.discriminatedUnion("event_type", [
|
|
|
818
2398
|
knowledgePromotedEventSchema,
|
|
819
2399
|
knowledgePromoteFailedEventSchema,
|
|
820
2400
|
knowledgeLayerChangedEventSchema,
|
|
2401
|
+
// v2.0.0-rc.37 NEW-24: dedicated old→new stable_id mapping event
|
|
2402
|
+
knowledgeIdRedirectEventSchema,
|
|
821
2403
|
knowledgeSlugRenamedEventSchema,
|
|
822
2404
|
knowledgeDemotedEventSchema,
|
|
823
2405
|
knowledgeArchivedEventSchema,
|
|
824
2406
|
knowledgeArchiveAttemptedEventSchema,
|
|
2407
|
+
// v2.0.0-rc.34 TASK-05: reverse of knowledge_archived
|
|
2408
|
+
knowledgeUnarchivedEventSchema,
|
|
825
2409
|
knowledgeDeferredEventSchema,
|
|
826
2410
|
knowledgeRejectedEventSchema,
|
|
827
2411
|
// v2.0 rc.5 TASK-014: knowledge_consumed (consumption tracking)
|
|
@@ -835,42 +2419,127 @@ var eventLedgerEventSchema = z9.discriminatedUnion("event_type", [
|
|
|
835
2419
|
// #24 when a glob in relevance_paths resolves to zero filesystem matches.
|
|
836
2420
|
knowledgePathDangledEventSchema,
|
|
837
2421
|
// v2.0.0-rc.7 T10: doctor_run — emitted by `fabric doctor` to drive Signal D.
|
|
838
|
-
doctorRunEventSchema
|
|
2422
|
+
doctorRunEventSchema,
|
|
2423
|
+
// v2.0.0-rc.9 TASK-003 (A3): relevance_migration_run — emitted by
|
|
2424
|
+
// `doctor --apply-lint` after the lint #26 frontmatter back-fill pass.
|
|
2425
|
+
relevanceMigrationRunEventSchema,
|
|
2426
|
+
// v2.0.0-rc.20 TASK-02: assistant_turn_observed — per-turn cite-policy
|
|
2427
|
+
// observation (raw KB: line text + parsed cite_ids/cite_tags + client).
|
|
2428
|
+
assistantTurnObservedEventSchema,
|
|
2429
|
+
// v2.0.0-rc.20 TASK-02: cite_policy_activated — session/policy-bump
|
|
2430
|
+
// marker recording when a given policy_version became active.
|
|
2431
|
+
citePolicyActivatedEventSchema,
|
|
2432
|
+
// v2.0.0-rc.24 TASK-01: cite_contract_policy_activated — drift-gated
|
|
2433
|
+
// idempotent marker opening the contract-policy audit window. Distinct
|
|
2434
|
+
// from cite_policy_activated so contract metrics get their own window.
|
|
2435
|
+
citeContractPolicyActivatedEventSchema,
|
|
2436
|
+
// v2.0.0-rc.22 Scope D T-D1: knowledge_meta_auto_healed — emitted by
|
|
2437
|
+
// loadActiveMeta when read-path drift triggers an in-place meta rebuild.
|
|
2438
|
+
knowledgeMetaAutoHealedEventSchema,
|
|
2439
|
+
// v2.0.0-rc.22 Scope A T3: events_rotated — emitted as the first line of
|
|
2440
|
+
// the post-rotation events.jsonl when sliding-window-by-age rotation moves
|
|
2441
|
+
// stale entries to events.archive/events-rotated-YYYY-MM-DD.jsonl.
|
|
2442
|
+
eventsRotatedEventSchema,
|
|
2443
|
+
// v2.0.0-rc.23 TASK-010 (e): serve_lock_cleared — emitted by
|
|
2444
|
+
// `fabric doctor --fix` when a stale `.fabric/.serve.lock` with a dead PID is
|
|
2445
|
+
// unlinked.
|
|
2446
|
+
serveLockClearedEventSchema,
|
|
2447
|
+
// v2.0.0-rc.23 TASK-007 (a-C2): knowledge_enriched — emitted by
|
|
2448
|
+
// `fabric doctor --enrich-descriptions` once per modified canonical knowledge
|
|
2449
|
+
// file when one or more of the four rc.23 description-grade frontmatter
|
|
2450
|
+
// fields is back-filled.
|
|
2451
|
+
knowledgeEnrichedEventSchema,
|
|
2452
|
+
// v2.0.0-rc.25 TASK-01: session_archive_attempted — emitted by the
|
|
2453
|
+
// fabric-archive skill at the end of every invocation. Drives Phase 0.0
|
|
2454
|
+
// cross-session digest, outcome-based rescan filter (skips user_dismissed),
|
|
2455
|
+
// covered_through_ts watermark, and `fabric doctor --archive-history`.
|
|
2456
|
+
sessionArchiveAttemptedEventSchema
|
|
839
2457
|
]);
|
|
840
2458
|
export {
|
|
841
2459
|
AGENTS_META_IDENTITY_SOURCES,
|
|
842
2460
|
AGENTS_META_LAYERS,
|
|
843
2461
|
AGENTS_META_TOPOLOGY_TYPES,
|
|
844
2462
|
AgentsMetaCountersSchema,
|
|
2463
|
+
BOOTSTRAP_CANONICAL,
|
|
2464
|
+
BOOTSTRAP_MARKER_BEGIN,
|
|
2465
|
+
BOOTSTRAP_MARKER_END,
|
|
2466
|
+
BOOTSTRAP_REGEX,
|
|
845
2467
|
FabExtractKnowledgeInputSchema,
|
|
846
2468
|
FabExtractKnowledgeInputShape,
|
|
847
2469
|
FabExtractKnowledgeOutputSchema,
|
|
848
2470
|
FabReviewInputSchema,
|
|
2471
|
+
FabReviewInputShape,
|
|
849
2472
|
FabReviewOutputSchema,
|
|
2473
|
+
FabReviewOutputShape,
|
|
2474
|
+
GLOBAL_BINDINGS_DIR,
|
|
2475
|
+
GLOBAL_REF_PATTERN,
|
|
2476
|
+
GLOBAL_STATE_DIR,
|
|
850
2477
|
KNOWLEDGE_TEST_INDEX_SCHEMA_VERSION,
|
|
851
2478
|
KNOWLEDGE_TYPE_CODES,
|
|
2479
|
+
KNOWN_SCOPE_PREFIXES,
|
|
852
2480
|
KnowledgeEntryFrontmatterSchema,
|
|
853
2481
|
KnowledgeTypeSchema,
|
|
2482
|
+
LEGACY_KB_MARKER_BEGIN,
|
|
2483
|
+
LEGACY_KB_MARKER_END,
|
|
2484
|
+
LEGACY_KB_REGEX,
|
|
854
2485
|
LayerSchema,
|
|
2486
|
+
MCP_STORE_AWARE_CONTRACTS,
|
|
2487
|
+
MCP_STORE_AWARE_TOOLS,
|
|
855
2488
|
MaturitySchema,
|
|
2489
|
+
ONBOARD_SLOT_NAMES,
|
|
2490
|
+
ONBOARD_SLOT_TOTAL,
|
|
2491
|
+
PARITY_CLIENTS,
|
|
2492
|
+
PARITY_SURFACES,
|
|
2493
|
+
PERSONAL_SCOPE,
|
|
2494
|
+
PERSONAL_STORE_SENTINEL,
|
|
2495
|
+
PROJECT_ROOT_SIGNALS,
|
|
856
2496
|
PROPOSED_REASON_DESCRIPTIONS,
|
|
857
2497
|
PROTECTED_TOKENS,
|
|
858
2498
|
ProposedReasonSchema,
|
|
2499
|
+
REDACTION_PLACEHOLDER_PREFIX,
|
|
2500
|
+
ResolverNotImplementedError,
|
|
2501
|
+
SCOPE_COORDINATE_PATTERN,
|
|
2502
|
+
STORES_ROOT_DIR,
|
|
2503
|
+
STORE_GITIGNORE,
|
|
2504
|
+
STORE_KNOWLEDGE_TYPE_DIRS,
|
|
2505
|
+
STORE_LAYOUT,
|
|
2506
|
+
STORE_PENDING_DIR,
|
|
2507
|
+
STORE_RESOLVER_WARNING_CODES,
|
|
2508
|
+
STORE_UUID_PATTERN,
|
|
859
2509
|
StableIdSchema,
|
|
2510
|
+
UID_SEGMENT_PATTERN,
|
|
2511
|
+
addMountedStore,
|
|
860
2512
|
agentsIdentitySourceSchema,
|
|
861
2513
|
agentsLayerSchema,
|
|
862
2514
|
agentsMetaNodeSchema,
|
|
863
2515
|
agentsMetaSchema,
|
|
864
2516
|
agentsTopologyTypeSchema,
|
|
2517
|
+
aggregatePendingAcrossStores,
|
|
865
2518
|
aiLedgerEntrySchema,
|
|
866
2519
|
allocateKnowledgeId,
|
|
867
2520
|
annotateIntentRequestSchema,
|
|
2521
|
+
archiveScanAnnotations,
|
|
2522
|
+
archiveScanInputSchema,
|
|
2523
|
+
archiveScanOutputSchema,
|
|
2524
|
+
assistantTurnObservedEventSchema,
|
|
868
2525
|
auditModeSchema,
|
|
2526
|
+
bindRequiredStore,
|
|
2527
|
+
bindingsSnapshotPath,
|
|
2528
|
+
bootstrapMarkerMigratedEventSchema,
|
|
2529
|
+
buildDebugBundle,
|
|
2530
|
+
buildFailureTrace,
|
|
869
2531
|
candidateFileEntrySchema,
|
|
2532
|
+
citeContractMetricsSchema,
|
|
2533
|
+
citeContractPolicyActivatedEventSchema,
|
|
2534
|
+
citeCoverageReportSchema,
|
|
2535
|
+
citeLayerTypeBreakdownSchema,
|
|
2536
|
+
citePolicyActivatedEventSchema,
|
|
870
2537
|
claudeHookPathMigratedEventSchema,
|
|
871
2538
|
claudeSkillPathMigratedEventSchema,
|
|
872
2539
|
clientPathsSchema,
|
|
873
2540
|
codexSkillPathMigratedEventSchema,
|
|
2541
|
+
createProjectRootResolver,
|
|
2542
|
+
createStoreResolver,
|
|
874
2543
|
createTranslator,
|
|
875
2544
|
defaultAgentsMetaCounters,
|
|
876
2545
|
defaultLayerFilterSchema,
|
|
@@ -879,17 +2548,24 @@ export {
|
|
|
879
2548
|
deriveAgentsMetaLayer,
|
|
880
2549
|
deriveAgentsMetaStableId,
|
|
881
2550
|
deriveAgentsMetaTopologyType,
|
|
2551
|
+
detachMountedStore,
|
|
882
2552
|
detectNodeLocale,
|
|
883
2553
|
doctorRunEventSchema,
|
|
884
2554
|
driftDetectedEventSchema,
|
|
885
2555
|
editIntentCheckedEventSchema,
|
|
886
2556
|
enMessages,
|
|
2557
|
+
entryScopeMetadataSchema,
|
|
887
2558
|
eventLedgerEventSchema,
|
|
888
2559
|
eventLedgerTruncatedEventSchema,
|
|
2560
|
+
eventsRotatedEventSchema,
|
|
2561
|
+
explainStore,
|
|
889
2562
|
fabExtractKnowledgeAnnotations,
|
|
890
2563
|
fabReviewAnnotations,
|
|
891
2564
|
fabricConfigSchema,
|
|
892
2565
|
fabricEventSchema,
|
|
2566
|
+
fabricLanguageSchema,
|
|
2567
|
+
findMountedStore,
|
|
2568
|
+
findStoreExecutableViolations,
|
|
893
2569
|
forensicAssertionCoverageSchema,
|
|
894
2570
|
forensicAssertionSchema,
|
|
895
2571
|
forensicCodeSampleSchema,
|
|
@@ -900,10 +2576,13 @@ export {
|
|
|
900
2576
|
forensicReportSchema,
|
|
901
2577
|
forensicSamplingBudgetSchema,
|
|
902
2578
|
forensicTopologySchema,
|
|
2579
|
+
formatGlobalRef,
|
|
903
2580
|
formatKnowledgeId,
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
2581
|
+
getPanelFieldByKey,
|
|
2582
|
+
getPanelFields,
|
|
2583
|
+
globalConfigSchema,
|
|
2584
|
+
globalRefSchema,
|
|
2585
|
+
hasSecrets,
|
|
907
2586
|
historyStateQuerySchema,
|
|
908
2587
|
humanLedgerEntrySchema,
|
|
909
2588
|
humanLockApproveRequestSchema,
|
|
@@ -918,7 +2597,11 @@ export {
|
|
|
918
2597
|
initContextSchema,
|
|
919
2598
|
initContextSourceEvidenceSchema,
|
|
920
2599
|
initScanCompletedEventSchema,
|
|
2600
|
+
initStore,
|
|
2601
|
+
installDiffAppliedEventSchema,
|
|
921
2602
|
isKnowledgeStableId,
|
|
2603
|
+
isPersonalLeakIntoSharedStore,
|
|
2604
|
+
isPersonalScope,
|
|
922
2605
|
knowledgeArchiveAttemptedEventSchema,
|
|
923
2606
|
knowledgeArchivedEventSchema,
|
|
924
2607
|
knowledgeConsumedEventSchema,
|
|
@@ -926,13 +2609,16 @@ export {
|
|
|
926
2609
|
knowledgeDeferredEventSchema,
|
|
927
2610
|
knowledgeDemotedEventSchema,
|
|
928
2611
|
knowledgeDriftDetectedEventSchema,
|
|
929
|
-
|
|
2612
|
+
knowledgeEnrichedEventSchema,
|
|
2613
|
+
knowledgeIdRedirectEventSchema,
|
|
930
2614
|
knowledgeLayerChangedEventSchema,
|
|
2615
|
+
knowledgeMetaAutoHealedEventSchema,
|
|
931
2616
|
knowledgePathDangledEventSchema,
|
|
932
2617
|
knowledgePromoteFailedEventSchema,
|
|
933
2618
|
knowledgePromoteStartedEventSchema,
|
|
934
2619
|
knowledgePromotedEventSchema,
|
|
935
2620
|
knowledgeProposedEventSchema,
|
|
2621
|
+
knowledgeProvenanceSchema,
|
|
936
2622
|
knowledgeRejectedEventSchema,
|
|
937
2623
|
knowledgeScopeDegradedEventSchema,
|
|
938
2624
|
knowledgeSectionsAnnotations,
|
|
@@ -944,10 +2630,14 @@ export {
|
|
|
944
2630
|
knowledgeTestIndexSchema,
|
|
945
2631
|
knowledgeTestLinkSchema,
|
|
946
2632
|
knowledgeTestOrphanAnnotationSchema,
|
|
2633
|
+
knowledgeUnarchivedEventSchema,
|
|
947
2634
|
ledgerAppendedEventSchema,
|
|
948
2635
|
ledgerEntrySchema,
|
|
949
2636
|
ledgerQuerySchema,
|
|
950
2637
|
ledgerSourceSchema,
|
|
2638
|
+
lintCrossStoreReferences,
|
|
2639
|
+
listStoreKnowledge,
|
|
2640
|
+
localKnowledgeIdSchema,
|
|
951
2641
|
lockApprovedEventSchema,
|
|
952
2642
|
lockDriftEventSchema,
|
|
953
2643
|
mcpConfigMigratedEventSchema,
|
|
@@ -956,7 +2646,17 @@ export {
|
|
|
956
2646
|
metaReconciledEventSchema,
|
|
957
2647
|
metaReconciledOnStartupEventSchema,
|
|
958
2648
|
metaUpdatedEventSchema,
|
|
2649
|
+
mountedStoreSchema,
|
|
2650
|
+
normalizeCiteTag,
|
|
959
2651
|
normalizeLocale,
|
|
2652
|
+
onboardSlotSchema,
|
|
2653
|
+
parityCapabilitySchema,
|
|
2654
|
+
parityClientExpectationSchema,
|
|
2655
|
+
parityClientSchema,
|
|
2656
|
+
parityMatrixSchema,
|
|
2657
|
+
paritySurfaceSchema,
|
|
2658
|
+
parseCiteLine,
|
|
2659
|
+
parseGlobalRef,
|
|
960
2660
|
parseKnowledgeId,
|
|
961
2661
|
pendingAutoArchivedEventSchema,
|
|
962
2662
|
planContextAnnotations,
|
|
@@ -964,10 +2664,52 @@ export {
|
|
|
964
2664
|
planContextHintOutputSchema,
|
|
965
2665
|
planContextInputSchema,
|
|
966
2666
|
planContextOutputSchema,
|
|
2667
|
+
projectRootGoldenCaseSchema,
|
|
2668
|
+
projectRootGoldenFileSchema,
|
|
2669
|
+
projectRootResolutionSchema,
|
|
2670
|
+
projectRootSignalSchema,
|
|
2671
|
+
projectRootSignalsSchema,
|
|
2672
|
+
readBindingsSnapshot,
|
|
2673
|
+
readKnowledgeAcrossStores,
|
|
2674
|
+
readSetEntrySchema,
|
|
2675
|
+
readSetGoldenCaseSchema,
|
|
2676
|
+
readSetGoldenFileSchema,
|
|
2677
|
+
readStoreIdentity,
|
|
967
2678
|
reapplyCompletedEventSchema,
|
|
2679
|
+
recallAnnotations,
|
|
2680
|
+
recallInputSchema,
|
|
2681
|
+
recallOutputSchema,
|
|
2682
|
+
recognizeStoreDir,
|
|
2683
|
+
redactSecrets,
|
|
2684
|
+
relevanceMigrationRunEventSchema,
|
|
2685
|
+
requiredStoreEntrySchema,
|
|
2686
|
+
resolveCandidates,
|
|
2687
|
+
resolveFabricLocale,
|
|
2688
|
+
resolveStoreQualifiedId,
|
|
2689
|
+
resolvedBindingsSnapshotSchema,
|
|
968
2690
|
ruleDescriptionIndexItemSchema,
|
|
969
2691
|
ruleDescriptionSchema,
|
|
2692
|
+
scanForSecrets,
|
|
2693
|
+
scopeCoordinateSchema,
|
|
2694
|
+
scopeRoot,
|
|
2695
|
+
selectionTokenTtlMsSchema,
|
|
2696
|
+
serveLockClearedEventSchema,
|
|
2697
|
+
sessionArchiveAttemptedEventSchema,
|
|
2698
|
+
storeAwareEntrySchema,
|
|
2699
|
+
storeCountersSchema,
|
|
2700
|
+
storeIdentitySchema,
|
|
2701
|
+
storeKnowledgeTypeDir,
|
|
2702
|
+
storeReadSetSchema,
|
|
2703
|
+
storeRelativePath,
|
|
2704
|
+
storeResolveInputSchema,
|
|
2705
|
+
storeResolverWarningCodeSchema,
|
|
2706
|
+
storeResolverWarningSchema,
|
|
2707
|
+
storeUuidSchema,
|
|
970
2708
|
structuredWarningSchema,
|
|
2709
|
+
uidSchema,
|
|
971
2710
|
withDerivedAgentsMetaNodeDefaults,
|
|
2711
|
+
writeBindingsSnapshot,
|
|
2712
|
+
writeTargetSchema,
|
|
2713
|
+
writtenToStoreSchema,
|
|
972
2714
|
zhCNMessages
|
|
973
2715
|
};
|