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