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