@dzhechkov/harness-core 0.3.128 → 0.3.130

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/sbom.json CHANGED
@@ -25,7 +25,7 @@
25
25
  "hashes": [
26
26
  {
27
27
  "alg": "SHA-256",
28
- "content": "d161d91fc1657d650584970e00ee393973ae625063e692319d2e28e816f91ea4"
28
+ "content": "b1691701ab0b6c51b194984178fa012168d1c2740258d64b759692d825c7cd4b"
29
29
  }
30
30
  ]
31
31
  },
@@ -95,7 +95,7 @@
95
95
  "hashes": [
96
96
  {
97
97
  "alg": "SHA-256",
98
- "content": "c9140e5af51f3af20a36c46909081d851c473190edb2de991b42f0735660fbf6"
98
+ "content": "f5baab841b3179512cf72fd12884869719f0a352b9e231a87dfa1b87b772974f"
99
99
  }
100
100
  ]
101
101
  },
@@ -105,7 +105,7 @@
105
105
  "hashes": [
106
106
  {
107
107
  "alg": "SHA-256",
108
- "content": "8ef6c9aa473d330ee8d934191fb2b715f4f07bba317edff6f212d67fe5146e91"
108
+ "content": "eb8f01ef67cb90a2d95b18ae1f10bb3ce2dd5855dc297402665a1fa621a8fb65"
109
109
  }
110
110
  ]
111
111
  },
@@ -115,7 +115,7 @@
115
115
  "hashes": [
116
116
  {
117
117
  "alg": "SHA-256",
118
- "content": "61c19dbe15ac1ae4a4fc9564c8d4eed1cd1290a6177ec46eaf07832a8c55b4f0"
118
+ "content": "f661d868e08152e9e293c83d9914e53c0c2ea52e0afc0ff49d1f8c320017eabd"
119
119
  }
120
120
  ]
121
121
  },
@@ -125,7 +125,7 @@
125
125
  "hashes": [
126
126
  {
127
127
  "alg": "SHA-256",
128
- "content": "3e73ff7641ad09ac8e7af287f0df4329d08dfa73633cd9b2620224e79f4810ef"
128
+ "content": "a994c29d7f265c129dccaf9c0e00b55eb7f6312af8112691035c3889a113668b"
129
129
  }
130
130
  ]
131
131
  },
@@ -1015,7 +1015,7 @@
1015
1015
  "hashes": [
1016
1016
  {
1017
1017
  "alg": "SHA-256",
1018
- "content": "6ee6d990aac7ee33204316a49cde4110818f1522ae89bcae0226d221490c246f"
1018
+ "content": "63b513058606e37cf080176b76be65b33f21ded4f05b25e78ec56e3a978ac16b"
1019
1019
  }
1020
1020
  ]
1021
1021
  },
@@ -1025,7 +1025,7 @@
1025
1025
  "hashes": [
1026
1026
  {
1027
1027
  "alg": "SHA-256",
1028
- "content": "0a509ce7802e48f49eca17166fc8dd85715791288b3021277b06435d854c32ff"
1028
+ "content": "92b4313165d607a7acb9321f490801f8b5d24a202050f7363f5df4836e4fc1de"
1029
1029
  }
1030
1030
  ]
1031
1031
  },
@@ -1035,7 +1035,7 @@
1035
1035
  "hashes": [
1036
1036
  {
1037
1037
  "alg": "SHA-256",
1038
- "content": "a7bfc772641de89a456cda793d23a920911313c87efc0f40ad44b33c6f7e1787"
1038
+ "content": "dd5e32274dee6e2bc787977f4dca188101e77ac74bc9599be56286ba12a3c32f"
1039
1039
  }
1040
1040
  ]
1041
1041
  },
@@ -1045,7 +1045,7 @@
1045
1045
  "hashes": [
1046
1046
  {
1047
1047
  "alg": "SHA-256",
1048
- "content": "ce0d259f4d632b2920bfc8b3f3899885e58ef71bd225b731e885c67081d1f61f"
1048
+ "content": "5e47bad5dd4e137a9ac61272419e6ad2f23166069776d5db364bc0d8f9d8dee3"
1049
1049
  }
1050
1050
  ]
1051
1051
  },
@@ -1065,7 +1065,7 @@
1065
1065
  "hashes": [
1066
1066
  {
1067
1067
  "alg": "SHA-256",
1068
- "content": "389e18ea7bfe22074dcd0ccc373fab234a4161333ae1bae4eb4466ffeaf166e6"
1068
+ "content": "1fb488eaaef87d92cd95ca18901508cfb1793057470c31df01f399dae6c9af6e"
1069
1069
  }
1070
1070
  ]
1071
1071
  },
@@ -1075,7 +1075,7 @@
1075
1075
  "hashes": [
1076
1076
  {
1077
1077
  "alg": "SHA-256",
1078
- "content": "d1c4136cad91ab8e3cee681f5ab7fde0696d5de1da61f6a69be423087f4d2eb9"
1078
+ "content": "55ae03d431dd90aa819f8ea28aa590aad076a2f0222bb076461ce627ac342187"
1079
1079
  }
1080
1080
  ]
1081
1081
  },
@@ -1085,7 +1085,7 @@
1085
1085
  "hashes": [
1086
1086
  {
1087
1087
  "alg": "SHA-256",
1088
- "content": "8bcb517e1d8277479344b5290c09e44ece12a7eca3d1bc5b1e61d4c355aaa2a9"
1088
+ "content": "7752efa7cba6b11dd7230b6d965f72a1b3a9e47e0c32fab619496d67f5f5ba22"
1089
1089
  }
1090
1090
  ]
1091
1091
  },
@@ -1215,7 +1215,7 @@
1215
1215
  "hashes": [
1216
1216
  {
1217
1217
  "alg": "SHA-256",
1218
- "content": "f58c60e77c4dd0a098b2ae076ae8db37cc1f0d63d95870e21083156cfd84f09c"
1218
+ "content": "f1c730b94dc591aa592b7b31b86982561f099680fb822e7da68045ec01d44a99"
1219
1219
  }
1220
1220
  ]
1221
1221
  },
@@ -1225,7 +1225,7 @@
1225
1225
  "hashes": [
1226
1226
  {
1227
1227
  "alg": "SHA-256",
1228
- "content": "282289f512e343985baaf3457ce39bd43927b3fd8ef597532f34e83db0c6cfd8"
1228
+ "content": "f59c1f9742028737b973c4129ac2b4f8e50c3c0b762f48ea2ce97f0a4f89c20a"
1229
1229
  }
1230
1230
  ]
1231
1231
  },
@@ -1235,7 +1235,7 @@
1235
1235
  "hashes": [
1236
1236
  {
1237
1237
  "alg": "SHA-256",
1238
- "content": "5d13af079c98511b2300b05f9f1ca3844578fa4cb110d89194ddde06afd96e19"
1238
+ "content": "f8f8e5a7139e6c898b466a208a14228752501845ca755c94d80e2200cb24d890"
1239
1239
  }
1240
1240
  ]
1241
1241
  },
@@ -1245,7 +1245,7 @@
1245
1245
  "hashes": [
1246
1246
  {
1247
1247
  "alg": "SHA-256",
1248
- "content": "ff59a5013fd97593f273bfee0de3cc22fb71ad51ad9609c57dc1efb57d35c0d4"
1248
+ "content": "ac7463223c47a36d03e2875995c98624c681bc36f04cd37490aa76616513d5aa"
1249
1249
  }
1250
1250
  ]
1251
1251
  },
@@ -1495,7 +1495,7 @@
1495
1495
  "hashes": [
1496
1496
  {
1497
1497
  "alg": "SHA-256",
1498
- "content": "2d837b3e03c48cb106dd76342c319bc949ff53907baf91ea40102093127290ab"
1498
+ "content": "9a74c9472688a4326b10065f61c9294b473baf232a27cf69f6ae7a74a5ce9bb6"
1499
1499
  }
1500
1500
  ]
1501
1501
  },
@@ -1505,7 +1505,7 @@
1505
1505
  "hashes": [
1506
1506
  {
1507
1507
  "alg": "SHA-256",
1508
- "content": "7b7f0b99bcf1d4d45233f33f059f520107258b71014064058b8f018a16375194"
1508
+ "content": "0631cf526a8aae076d5512bcc75c629ea69830f65aa267ade03028e532a2a923"
1509
1509
  }
1510
1510
  ]
1511
1511
  },
@@ -1515,7 +1515,7 @@
1515
1515
  "hashes": [
1516
1516
  {
1517
1517
  "alg": "SHA-256",
1518
- "content": "db3a0e92b040e83b792ee56f759e036a9019d05b401d65cd366e716f00a08578"
1518
+ "content": "73fa2d3bcedb0158a2860171b66046aa67c7aa1aab80a93502588202f0aed09e"
1519
1519
  }
1520
1520
  ]
1521
1521
  },
@@ -1525,7 +1525,7 @@
1525
1525
  "hashes": [
1526
1526
  {
1527
1527
  "alg": "SHA-256",
1528
- "content": "002462c04676596add4eed874909da0ca4310d927fe9d04d79357a22ff76480a"
1528
+ "content": "abdfa155fca15e8aa950430d201c2e6754872c0b02d0201a10c5f0923210373a"
1529
1529
  }
1530
1530
  ]
1531
1531
  },
@@ -2089,6 +2089,46 @@
2089
2089
  }
2090
2090
  ]
2091
2091
  },
2092
+ {
2093
+ "type": "file",
2094
+ "name": "dist/skills-verify.d.ts",
2095
+ "hashes": [
2096
+ {
2097
+ "alg": "SHA-256",
2098
+ "content": "a2352edd8bd41e74dd5a7939f00d3166b24661c3e5a11fa0443937713fee7452"
2099
+ }
2100
+ ]
2101
+ },
2102
+ {
2103
+ "type": "file",
2104
+ "name": "dist/skills-verify.d.ts.map",
2105
+ "hashes": [
2106
+ {
2107
+ "alg": "SHA-256",
2108
+ "content": "e6cab46f60962e86bf738a71f638ef38e1114f9b88a892417abdf6a0e8c31795"
2109
+ }
2110
+ ]
2111
+ },
2112
+ {
2113
+ "type": "file",
2114
+ "name": "dist/skills-verify.js",
2115
+ "hashes": [
2116
+ {
2117
+ "alg": "SHA-256",
2118
+ "content": "a755e50fc0efaa79f9aec3cb4b0c1e42bf389c6b05f7f2e3f539bf04dd72e530"
2119
+ }
2120
+ ]
2121
+ },
2122
+ {
2123
+ "type": "file",
2124
+ "name": "dist/skills-verify.js.map",
2125
+ "hashes": [
2126
+ {
2127
+ "alg": "SHA-256",
2128
+ "content": "fa859ddaa63747473d92d1efc701975b89c4458ff53c49f1bc2bf6a83517f8df"
2129
+ }
2130
+ ]
2131
+ },
2092
2132
  {
2093
2133
  "type": "file",
2094
2134
  "name": "dist/skills.d.ts",
@@ -2335,7 +2375,7 @@
2335
2375
  "hashes": [
2336
2376
  {
2337
2377
  "alg": "SHA-256",
2338
- "content": "7e181b3d05e7aac7acaf496a8eb58773abef14bd2e11e2f8aa8bed55ae69326b"
2378
+ "content": "2bc60f782f3b2f9ee179894b88d8b2b9ff487f286c17f3d3dfd7f0ca0d640ffc"
2339
2379
  }
2340
2380
  ]
2341
2381
  },
@@ -2345,7 +2385,7 @@
2345
2385
  "hashes": [
2346
2386
  {
2347
2387
  "alg": "SHA-256",
2348
- "content": "4b70f02d8954195ff16a19df746f5a1cf6f9c00f420621a692fe381221bba081"
2388
+ "content": "2a30a5bd7b8caf0e1cca2587817d25d9b0a366162ca098d5464f9783cdc2311d"
2349
2389
  }
2350
2390
  ]
2351
2391
  },
@@ -2355,7 +2395,7 @@
2355
2395
  "hashes": [
2356
2396
  {
2357
2397
  "alg": "SHA-256",
2358
- "content": "a1076a6870b1cfb1c0fc47525e8bf9357887be062cbd124d6145996ad8b81da7"
2398
+ "content": "c0d917225ced953324609cb086fff6d6a2f31dead7dad470a31ec5d6bb257a32"
2359
2399
  }
2360
2400
  ]
2361
2401
  },
@@ -2365,7 +2405,7 @@
2365
2405
  "hashes": [
2366
2406
  {
2367
2407
  "alg": "SHA-256",
2368
- "content": "82b2a767216bd3688100189a38aa331515e30696310d086ff2a9ea934172f3df"
2408
+ "content": "70e3c78890c71f0bb1cdd66bc2f787ead25c88edc130449d71003275e5adf57b"
2369
2409
  }
2370
2410
  ]
2371
2411
  },
@@ -2415,7 +2455,7 @@
2415
2455
  "hashes": [
2416
2456
  {
2417
2457
  "alg": "SHA-256",
2418
- "content": "10333f357c5fc55ad72780e1f8c8b0626fca13955ca21faa1588448e0f111ff1"
2458
+ "content": "efe1f6f372dada19c2889e5ed4ee3fe930602ed77ff9e7695ab59c47978dc340"
2419
2459
  }
2420
2460
  ]
2421
2461
  },
@@ -2435,7 +2475,7 @@
2435
2475
  "hashes": [
2436
2476
  {
2437
2477
  "alg": "SHA-256",
2438
- "content": "3347529bd57799df27e1c209a7a480348b53b511f26f5fd863cc21a39c6d5b53"
2478
+ "content": "91f8d26b81e3262bc9e3b4ca357165eaed5d889660ef60f18b63e483009ea44e"
2439
2479
  }
2440
2480
  ]
2441
2481
  },
@@ -2665,7 +2705,7 @@
2665
2705
  "hashes": [
2666
2706
  {
2667
2707
  "alg": "SHA-256",
2668
- "content": "4ab5be98ff44ccdf428a60976bfd9e6c728ad88c7a76c56d1c11912727fe7c62"
2708
+ "content": "c224021d9de3fbfd777ad74dc2d65baefa112b98e6fcee8eeac4bc0c83fa8b60"
2669
2709
  }
2670
2710
  ]
2671
2711
  },
@@ -2675,7 +2715,7 @@
2675
2715
  "hashes": [
2676
2716
  {
2677
2717
  "alg": "SHA-256",
2678
- "content": "517a2346f10e1331aa9a33a7d24d25fd01bcb9e365b6c153f0631e6cb64208da"
2718
+ "content": "041fea2a00543016e0d2d9c5fc45df0df3bd97744c1705f95f6bb73725f03aee"
2679
2719
  }
2680
2720
  ]
2681
2721
  },
@@ -2715,7 +2755,7 @@
2715
2755
  "hashes": [
2716
2756
  {
2717
2757
  "alg": "SHA-256",
2718
- "content": "55cfcd5cd45a8bec20c10ea0c7f40ccd3a57bce84783e9d7fa563eac4ba7f347"
2758
+ "content": "dba61149547898122304b11d4be377aed17ad822b0f4a017d76815ddb295eb0a"
2719
2759
  }
2720
2760
  ]
2721
2761
  },
@@ -2775,7 +2815,7 @@
2775
2815
  "hashes": [
2776
2816
  {
2777
2817
  "alg": "SHA-256",
2778
- "content": "b7fa9bd88206c40c6e8e8c1cc42bfdb409595cb86db1769e6597d2315bd65b23"
2818
+ "content": "b4a3c6b3fc2e8338efeee729038a01e3881dc578b65427ffbb03c236e160b470"
2779
2819
  }
2780
2820
  ]
2781
2821
  },
@@ -2919,6 +2959,16 @@
2919
2959
  }
2920
2960
  ]
2921
2961
  },
2962
+ {
2963
+ "type": "file",
2964
+ "name": "src/skills-verify.ts",
2965
+ "hashes": [
2966
+ {
2967
+ "alg": "SHA-256",
2968
+ "content": "7d71fd31d41d2d3b369046161920edde3825dd620ec5e4ea503d59b56abc5d94"
2969
+ }
2970
+ ]
2971
+ },
2922
2972
  {
2923
2973
  "type": "file",
2924
2974
  "name": "src/skills.ts",
@@ -2985,7 +3035,7 @@
2985
3035
  "hashes": [
2986
3036
  {
2987
3037
  "alg": "SHA-256",
2988
- "content": "5d1189cca886a9e34112e74706e2610eaf7449a83268c13d005cdd84f5bf77a9"
3038
+ "content": "9707fa46b1f92cfa75e45c6619e01ef8f74bb5f50a913b778edfe6143d818d8a"
2989
3039
  }
2990
3040
  ]
2991
3041
  },
@@ -3419,6 +3469,16 @@
3419
3469
  }
3420
3470
  ]
3421
3471
  },
3472
+ {
3473
+ "type": "file",
3474
+ "name": "test/lesson-quarantine.test.ts",
3475
+ "hashes": [
3476
+ {
3477
+ "alg": "SHA-256",
3478
+ "content": "61931781195ab6093482060120f537a047223c6f345ce8c1809a81655ffb74d6"
3479
+ }
3480
+ ]
3481
+ },
3422
3482
  {
3423
3483
  "type": "file",
3424
3484
  "name": "test/mcp-scan.test.ts",
@@ -3639,6 +3699,16 @@
3639
3699
  }
3640
3700
  ]
3641
3701
  },
3702
+ {
3703
+ "type": "file",
3704
+ "name": "test/skills-verify.test.ts",
3705
+ "hashes": [
3706
+ {
3707
+ "alg": "SHA-256",
3708
+ "content": "99e16fe36ae35f5493452dfe0b26265061467b14d98e60cdcb30265fa63d97b5"
3709
+ }
3710
+ ]
3711
+ },
3642
3712
  {
3643
3713
  "type": "file",
3644
3714
  "name": "test/statusline.test.ts",
@@ -484,6 +484,52 @@ export async function importVectorsToAgentdb(
484
484
  }
485
485
  }
486
486
 
487
+ /**
488
+ * lesson-quarantine: clear the `qStatus` marker from mirrored rows after a promotion — the hook
489
+ * daemon reads ONLY this mirror's metadata, so a promoted lesson must stop being excluded there
490
+ * too. Best-effort, same custody model as {@link bumpAgentdbUses} (missing db/deps ⇒ no-op).
491
+ */
492
+ export function clearAgentdbQuarantine(
493
+ projectRoot: string,
494
+ dzIds: readonly string[],
495
+ opts: { dbPath?: string } = {},
496
+ ): { cleared: number; error?: string } {
497
+ if (dzIds.length === 0) return { cleared: 0 };
498
+ const dbFile = resolveAgentdbPath(projectRoot, opts.dbPath);
499
+ if (!existsSync(dbFile)) return { cleared: 0 };
500
+ let Database: new (p: string) => UpsertDb;
501
+ try {
502
+ const req = createRequire(join(projectRoot, 'package.json'));
503
+ Database = req('better-sqlite3') as new (p: string) => UpsertDb;
504
+ } catch {
505
+ return { cleared: 0, error: DEPS_MISSING };
506
+ }
507
+ try {
508
+ const db = new Database(dbFile);
509
+ try {
510
+ db.pragma('journal_mode = WAL');
511
+ db.pragma('busy_timeout = 5000');
512
+ db.exec(REASONING_BANK_SCHEMA);
513
+ const stmt = db.prepare(
514
+ "UPDATE reasoning_patterns SET metadata = json_remove(metadata, '$.qStatus', '$.quarantinedAt') WHERE json_extract(metadata, '$.dzId') = ? AND json_extract(metadata, '$.qStatus') = 'quarantined'",
515
+ );
516
+ const tx = db.transaction(() => {
517
+ let cleared = 0;
518
+ for (const dzId of dzIds) {
519
+ const r = stmt.run(dzId);
520
+ cleared += Number((r as unknown as { changes?: number }).changes ?? 0);
521
+ }
522
+ return cleared;
523
+ });
524
+ return { cleared: tx() };
525
+ } finally {
526
+ db.close();
527
+ }
528
+ } catch (err) {
529
+ return { cleared: 0, error: `quarantine clear failed: ${err instanceof Error ? err.message : String(err)}` };
530
+ }
531
+ }
532
+
487
533
  export function bumpAgentdbUses(
488
534
  projectRoot: string,
489
535
  dzIds: readonly string[],
package/src/index.ts CHANGED
@@ -40,8 +40,8 @@ export { benchmarkSkill, benchmarkSkills, compareSkills } from './benchmark.js';
40
40
  export { buildRegistry, searchRegistry, filterByCategory, skillPackBaseDirs, discoverSkillPackDirs } from './registry.js';
41
41
  export { recommend } from './recommend.js';
42
42
  export { pretrain } from './pretrain.js';
43
- export { loadPatterns, loadSessions, computePatternBoost, readLearningConfig, readMemoryLearningConfig, BOOST_CAP, recordPattern, loadStorePatternsSync, loadStoreRecords, patternToRecord, recordToPattern, patternRecordId, patternIdentityOf, dreamRecordId, isMirrorableLearning, consolidateSessions, recallPatterns, pruneNoisePatterns, removePatternsByIds, snapshotStore, readReinforcementState, encodeReinforcementState, reinforcePattern, updateReinforcementState, storeStats, lessonDeltaReport, lessonDeltaMap } from './patterns.js';
44
- export type { PatternRecord, SessionRecord, LearningConfig, MemoryLearningConfig, LoadOptions, ConsolidateResult, ConsolidateOptions, SqliteBackendMode, RecallHit, SessionsSource, PruneNoiseResult, RemovePatternsResult, SnapshotStoreResult, ReinforcementState, ReinforcePatternResult, StoreStats, LessonDeltaReport, LessonDeltaRow } from './patterns.js';
43
+ export { loadPatterns, loadSessions, computePatternBoost, readLearningConfig, readMemoryLearningConfig, BOOST_CAP, recordPattern, loadStorePatternsSync, loadStoreRecords, patternToRecord, recordToPattern, patternRecordId, patternIdentityOf, dreamRecordId, isMirrorableLearning, consolidateSessions, recallPatterns, pruneNoisePatterns, removePatternsByIds, snapshotStore, readReinforcementState, encodeReinforcementState, reinforcePattern, updateReinforcementState, storeStats, lessonDeltaReport, lessonDeltaMap, readQuarantineState, encodeQuarantineState, promotePatterns, quarantineExpiryCandidates, pruneQuarantinePatterns } from './patterns.js';
44
+ export type { PatternRecord, SessionRecord, LearningConfig, MemoryLearningConfig, LoadOptions, ConsolidateResult, ConsolidateOptions, SqliteBackendMode, RecallHit, SessionsSource, PruneNoiseResult, RemovePatternsResult, SnapshotStoreResult, ReinforcementState, ReinforcePatternResult, StoreStats, LessonDeltaReport, LessonDeltaRow, QuarantineState, PromoteResult, QuarantineExpiryCandidate } from './patterns.js';
45
45
  export { DEFAULT_REINFORCE_THRESHOLD, NoopLearningBackend, NativeReinforcementBackend, resolveLearningBackend, isLearningSignalBackend } from './learning-backend.js';
46
46
  export type { LearningSignalBackend, LearningSignalStats, LearningSample, SignalCandidate, EnhanceContext, TrainingResult, LearningBackendMode } from './learning-backend.js';
47
47
  export {
@@ -96,7 +96,7 @@ export type {
96
96
  export { runSetup, generateHooksConfig, generateAgentdbWriter, writerVersionOf, AGENTDB_WRITER_VERSION } from './setup.js';
97
97
  export { statuslineData, readFeatureAdrState, writeFeatureAdrState, featureAdrStatePath } from './statusline.js';
98
98
  export type { StatuslineData, FeatureAdrState, WriteFeatureAdrStateInput } from './statusline.js';
99
- export { indexPatternsToAgentdb, resolveAgentdbPath, searchAgentdbPatterns, listAgentdbDzIds, resolveAgentdbEmbedder, cosineSimilarity, importVectorsToAgentdb, reindexAgentdbRows, bumpAgentdbUses } from './agentdb-index.js';
99
+ export { indexPatternsToAgentdb, resolveAgentdbPath, searchAgentdbPatterns, listAgentdbDzIds, resolveAgentdbEmbedder, cosineSimilarity, importVectorsToAgentdb, reindexAgentdbRows, bumpAgentdbUses, clearAgentdbQuarantine } from './agentdb-index.js';
100
100
  export type { AgentdbSearchHit, AgentdbSearchResult, AgentdbImportRow } from './agentdb-index.js';
101
101
  export { DEFAULT_EMBED_MODEL, LEGACY_EMBED_MODEL, DEFAULT_EMBED_DIM, KNOWN_EMBED_DIMS, resolveEmbedModel, readEmbedManifest, writeEmbedManifest, embedManifestPath, legacyEmbedManifest } from './embedding-config.js';
102
102
  export type { EmbedModelConfig, EmbedModelSource, EmbedManifest } from './embedding-config.js';
@@ -317,3 +317,7 @@ export * from './bto-optimize.js';
317
317
  export * from './discrimination-gate.js';
318
318
  export * from './guard.js';
319
319
  export * from './delivery-check.js';
320
+
321
+ // Skill-registration gate (feature skills-verify, ADR-001) — static layout scan + the deterministic
322
+ // `system/init` listing. Fail-closed: an unobservable registration is `inconclusive`, never `pass`.
323
+ export * from './skills-verify.js';
@@ -115,9 +115,13 @@ export class NativeReinforcementBackend implements LearningSignalBackend {
115
115
  let failed = 0;
116
116
  let error: string | undefined;
117
117
  for (const sample of batch) {
118
+ // lesson-quarantine (CRITICAL, cross-model QE): a `recall-hit` sample is EXPOSURE, not
119
+ // confirmation — it must update reinforcement stats WITHOUT lifting quarantine. Only an
120
+ // explicit `reinforce` sample promotes (the ADR's no-promotion-by-exposure invariant).
118
121
  const r = await reinforcePattern(this.projectRoot, sample.dzId, {
119
122
  ts: sample.ts,
120
123
  ...(sample.reward !== undefined ? { reward: sample.reward } : {}),
124
+ ...(sample.kind === 'recall-hit' ? { exposure: true } : {}),
121
125
  });
122
126
  if (r.ok) flushed += 1;
123
127
  else {