@agentproto/corpus 0.1.0-alpha.2 → 0.1.0-alpha.4

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/index.mjs CHANGED
@@ -1,9 +1,9 @@
1
1
  export { systemClock } from './chunk-KYX2DTEH.mjs';
2
- import { REFINED_KIND_SCHEMA, resolveKnowledge } from './chunk-3P23OX5X.mjs';
3
- export { REFINED_KIND_SCHEMA, isRefinedKind, resolveKnowledge } from './chunk-3P23OX5X.mjs';
2
+ import { REFINED_KIND_SCHEMA, resolveKnowledge } from './chunk-JV6VRZ6U.mjs';
3
+ export { REFINED_KIND_SCHEMA, isRefinedKind, resolveKnowledge } from './chunk-JV6VRZ6U.mjs';
4
4
  import { CandidatesSidecar } from './chunk-UPX26MYH.mjs';
5
5
  export { CandidatesSidecar, SidecarDuplicateError, SidecarNotFoundError } from './chunk-UPX26MYH.mjs';
6
- import matter from 'gray-matter';
6
+ import matter6 from 'gray-matter';
7
7
  import { createHash } from 'crypto';
8
8
  import { z } from 'zod';
9
9
  import { parse, stringify } from 'yaml';
@@ -379,7 +379,7 @@ var CorpusWorkspaceReader = class {
379
379
  };
380
380
  for (const path of mdFiles) {
381
381
  const content = await this.opts.fs.readFile(path);
382
- const parsed = matter(content);
382
+ const parsed = matter6(content);
383
383
  const file = {
384
384
  // Workspace-relative path. The walk returns paths anchored at
385
385
  // the host's storage root (which already includes `root` for
@@ -535,7 +535,7 @@ var CorpusWorkspaceWriter = class _CorpusWorkspaceWriter {
535
535
  }
536
536
  };
537
537
  function serializeMarkdown(doc) {
538
- return matter.stringify(doc.body.startsWith("\n") ? doc.body : "\n" + doc.body, doc.frontmatter);
538
+ return matter6.stringify(doc.body.startsWith("\n") ? doc.body : "\n" + doc.body, doc.frontmatter);
539
539
  }
540
540
 
541
541
  // src/importers/runner.ts
@@ -673,7 +673,7 @@ function serializeSource(source, archiveDirSegment, clock) {
673
673
  }
674
674
  };
675
675
  }
676
- return matter.stringify(
676
+ return matter6.stringify(
677
677
  source.body.startsWith("\n") ? source.body : "\n" + source.body,
678
678
  fm
679
679
  );
@@ -995,7 +995,9 @@ var DistillRunner = class {
995
995
  const items = await this.opts.distiller.distill({
996
996
  title: source.title,
997
997
  body: source.body,
998
- ...source.tags ? { tags: source.tags } : {}
998
+ ...source.tags ? { tags: source.tags } : {},
999
+ ...source.kinds ? { kinds: source.kinds } : {},
1000
+ ...source.instruction ? { instruction: source.instruction } : {}
999
1001
  });
1000
1002
  const year = this.opts.clock.now().getUTCFullYear();
1001
1003
  const flat = this.opts.layout === "flat";
@@ -1028,7 +1030,7 @@ function serializeEntry(item, slug, source, clock) {
1028
1030
  sources: [source.id],
1029
1031
  // ← derivedFrom / provenance edge
1030
1032
  confidence: typeof item.confidence === "number" ? item.confidence : 0.7,
1031
- tags: dedupeTags(item.tags, source.tags),
1033
+ tags: withAspect(dedupeTags(item.tags, source.tags), source.aspect),
1032
1034
  metadata: {
1033
1035
  corpus: {
1034
1036
  status: "active",
@@ -1042,7 +1044,14 @@ function serializeEntry(item, slug, source, clock) {
1042
1044
  }
1043
1045
  };
1044
1046
  const body = item.body.trim();
1045
- return matter.stringify(body.startsWith("\n") ? body : "\n" + body, fm);
1047
+ return matter6.stringify(body.startsWith("\n") ? body : "\n" + body, fm);
1048
+ }
1049
+ function withAspect(tags, aspect) {
1050
+ if (!aspect) return [...tags];
1051
+ const value = sanitizeTag(aspect);
1052
+ if (!value) return [...tags];
1053
+ const facet = `aspect:${value}`;
1054
+ return tags.includes(facet) ? [...tags] : [facet, ...tags];
1046
1055
  }
1047
1056
  function dedupeTags(a, b) {
1048
1057
  const out = /* @__PURE__ */ new Set();
@@ -1064,10 +1073,16 @@ var DISTILLED_ITEM = z.object({
1064
1073
  tags: z.array(z.string()).optional()
1065
1074
  }).loose();
1066
1075
  function buildDistillPrompt(input, maxItems) {
1067
- return `You distill a raw source (a video transcript or article) into REFINED, reusable knowledge for an AI operator. Extract the durable insights \u2014 not a summary of the video, but the transferable lessons.
1076
+ const lensBlock = input.instruction?.trim() ? `LENS \u2014 read the source THROUGH this aspect, extract ONLY what serves it:
1077
+ ${input.instruction.trim()}
1078
+
1079
+ ` : "";
1080
+ const kinds = input.kinds?.length ? input.kinds : ["principle", "pattern", "critique", "summary", "example"];
1081
+ const kindUnion = kinds.map((k) => `"${k}"`).join(" | ");
1082
+ return `${lensBlock}You distill a raw source (a video transcript or article) into REFINED, reusable knowledge for an AI operator. Extract the durable insights \u2014 not a summary of the video, but the transferable lessons.
1068
1083
 
1069
1084
  Return a JSON array (max ${maxItems} items). Each item:
1070
- { "kind": one of "principle" | "pattern" | "critique" | "summary" | "example",
1085
+ { "kind": one of ${kindUnion},
1071
1086
  "title": short imperative/declarative title,
1072
1087
  "body": 2-5 sentences, SELF-CONTAINED (no "the speaker says"), the actual insight,
1073
1088
  "confidence": 0-1, "tags": [short topic tags] }
@@ -1125,7 +1140,7 @@ async function scanDistilledSourceIds(fs) {
1125
1140
  if (!rel.endsWith(".md")) continue;
1126
1141
  const path = rel.startsWith("entries/") ? rel : `entries/${rel}`;
1127
1142
  try {
1128
- const fm = ENTRY_SOURCES.parse(matter(await fs.readFile(path)).data);
1143
+ const fm = ENTRY_SOURCES.parse(matter6(await fs.readFile(path)).data);
1129
1144
  if (fm.sources) for (const s of fm.sources) ids.add(s);
1130
1145
  } catch {
1131
1146
  }
@@ -1133,6 +1148,19 @@ async function scanDistilledSourceIds(fs) {
1133
1148
  return ids;
1134
1149
  }
1135
1150
 
1151
+ // src/distill/model-distiller.ts
1152
+ function modelDistiller(model, opts = {}) {
1153
+ const maxItems = opts.maxItems ?? 8;
1154
+ return {
1155
+ async distill(input) {
1156
+ const prompt = buildDistillPrompt(input, maxItems);
1157
+ const { result } = await model.complete({ prompt });
1158
+ const text = typeof result === "string" ? result : JSON.stringify(result);
1159
+ return parseItems(text);
1160
+ }
1161
+ };
1162
+ }
1163
+
1136
1164
  // src/distill/registry.ts
1137
1165
  function createDistillRegistry() {
1138
1166
  const descriptors = /* @__PURE__ */ new Map();
@@ -1161,47 +1189,309 @@ function createDistillRegistry() {
1161
1189
  };
1162
1190
  }
1163
1191
 
1164
- // src/distill/run.ts
1165
- async function runDistill(descriptor, scope) {
1192
+ // src/distill/lens.ts
1193
+ function lensAspect(lens) {
1194
+ return lens.aspect ?? lens.id;
1195
+ }
1196
+ function lensAspectTag(lens) {
1197
+ return `aspect:${lensAspect(lens)}`;
1198
+ }
1199
+
1200
+ // src/distill/generate.ts
1201
+ async function distillFromImporter(opts) {
1166
1202
  const report = {
1167
- descriptorId: descriptor.id,
1168
- scopeId: scope.id,
1169
1203
  unitsConsidered: 0,
1170
1204
  unitsDistilled: 0,
1171
1205
  entriesWritten: 0,
1172
- skipped: 0
1206
+ skipped: 0,
1207
+ unchanged: 0
1173
1208
  };
1174
- const target = await descriptor.target(scope);
1175
- const distilled = await scanDistilledSourceIds(target.fs);
1176
- const binding = descriptor.bind(scope, target);
1177
- const config = await binding.prepare(distilled);
1178
- if (!config) return report;
1179
1209
  const runner = new DistillRunner({
1180
- fs: target.fs,
1181
- clock: target.clock,
1182
- distiller: descriptor.distiller(scope)
1210
+ fs: opts.fs,
1211
+ clock: opts.clock,
1212
+ distiller: opts.distiller,
1213
+ ...opts.layout ? { layout: opts.layout } : {}
1183
1214
  });
1184
- for await (const imported of binding.importer.enumerate({
1185
- importerId: descriptor.id,
1186
- config
1215
+ const provenanceId = opts.provenanceId ?? ((s) => s.slug);
1216
+ const lensId = opts.lens?.id;
1217
+ for await (const imported of opts.importer.enumerate({
1218
+ importerId: opts.importerId,
1219
+ config: opts.config
1187
1220
  })) {
1188
1221
  report.unitsConsidered++;
1222
+ const sourceId = provenanceId(imported);
1223
+ if (opts.index && await opts.index.isDistilled(sourceId, imported.contentHash, lensId)) {
1224
+ report.unchanged++;
1225
+ continue;
1226
+ }
1189
1227
  const source = {
1190
- id: binding.provenanceId(imported),
1228
+ id: sourceId,
1191
1229
  title: imported.title,
1192
1230
  body: imported.body,
1193
- ...imported.tags ? { tags: imported.tags } : {}
1231
+ ...imported.tags ? { tags: imported.tags } : {},
1232
+ ...opts.lens?.prompt ? { instruction: opts.lens.prompt } : {},
1233
+ ...opts.lens?.kinds ? { kinds: opts.lens.kinds } : {},
1234
+ ...opts.lens ? { aspect: lensAspect(opts.lens) } : {}
1194
1235
  };
1195
1236
  try {
1196
1237
  const r = await runner.run(source);
1197
1238
  if (r.entryPaths.length > 0) report.unitsDistilled++;
1198
1239
  report.entriesWritten += r.entryPaths.length;
1199
1240
  report.skipped += r.skipped.length;
1241
+ if (opts.index) {
1242
+ await opts.index.record({
1243
+ sourceId,
1244
+ ...lensId ? { lensId } : {},
1245
+ title: imported.title,
1246
+ distilledAt: opts.clock.now().toISOString(),
1247
+ ...opts.engine ? { engine: opts.engine } : {},
1248
+ ...imported.contentHash ? { contentHash: imported.contentHash } : {},
1249
+ entryCount: r.entryPaths.length,
1250
+ ...r.entryPaths.length ? { entryPaths: r.entryPaths } : {}
1251
+ });
1252
+ }
1200
1253
  } catch {
1201
1254
  }
1202
1255
  }
1203
1256
  return report;
1204
1257
  }
1258
+
1259
+ // src/distill/run.ts
1260
+ async function runDistill(descriptor, scope, opts = {}) {
1261
+ const empty = {
1262
+ unitsConsidered: 0,
1263
+ unitsDistilled: 0,
1264
+ entriesWritten: 0,
1265
+ skipped: 0,
1266
+ unchanged: 0
1267
+ };
1268
+ const target = await descriptor.target(scope);
1269
+ const distilled = await scanDistilledSourceIds(target.fs);
1270
+ const binding = descriptor.bind(scope, target);
1271
+ const config = await binding.prepare(distilled);
1272
+ if (!config) {
1273
+ return { descriptorId: descriptor.id, scopeId: scope.id, ...empty };
1274
+ }
1275
+ const core = await distillFromImporter({
1276
+ fs: target.fs,
1277
+ clock: target.clock,
1278
+ distiller: descriptor.distiller(scope),
1279
+ importer: binding.importer,
1280
+ importerId: descriptor.id,
1281
+ config,
1282
+ provenanceId: binding.provenanceId,
1283
+ ...opts.index ? { index: opts.index } : {},
1284
+ ...opts.engine ? { engine: opts.engine } : {},
1285
+ ...opts.lens ? { lens: opts.lens } : {}
1286
+ });
1287
+ return { descriptorId: descriptor.id, scopeId: scope.id, ...core };
1288
+ }
1289
+ var DISTILL_INDEX_PATH = "_distill-index.yaml";
1290
+ var DistillIndex = class {
1291
+ fs;
1292
+ path;
1293
+ constructor(opts) {
1294
+ this.fs = opts.fs;
1295
+ this.path = opts.path ?? DISTILL_INDEX_PATH;
1296
+ }
1297
+ /** Every record on disk. Empty for a fresh corpus (no file yet). */
1298
+ async load() {
1299
+ if (!await this.fs.exists(this.path)) return [];
1300
+ const content = await this.fs.readFile(this.path);
1301
+ if (!content.trim()) return [];
1302
+ const parsed = parse(content);
1303
+ if (!parsed || !Array.isArray(parsed.runs)) return [];
1304
+ return parsed.runs;
1305
+ }
1306
+ /**
1307
+ * The record for a `(sourceId, lensId)` pair, or null if never distilled.
1308
+ * `lensId` undefined matches the generic lens-less row (back-compat).
1309
+ */
1310
+ async get(sourceId, lensId) {
1311
+ const rows = await this.load();
1312
+ return rows.find((r) => r.sourceId === sourceId && r.lensId === lensId) ?? null;
1313
+ }
1314
+ /**
1315
+ * True if the `(source, lens)` pair was distilled with a matching content
1316
+ * hash (when given). Each lens has independent cadence over the same source.
1317
+ */
1318
+ async isDistilled(sourceId, contentHash, lensId) {
1319
+ const row = await this.get(sourceId, lensId);
1320
+ if (!row) return false;
1321
+ if (contentHash === void 0) return true;
1322
+ return row.contentHash === contentHash;
1323
+ }
1324
+ /**
1325
+ * Upsert a record by `(sourceId, lensId)`. Re-distilling overwrites that
1326
+ * pair's row (cadence is "latest run wins") while leaving the same source's
1327
+ * other lens rows untouched; a new pair appends. Returns the full list.
1328
+ */
1329
+ async record(row) {
1330
+ const existing = await this.load();
1331
+ const idx = existing.findIndex(
1332
+ (r) => r.sourceId === row.sourceId && r.lensId === row.lensId
1333
+ );
1334
+ const next = idx === -1 ? [...existing, row] : [...existing.slice(0, idx), row, ...existing.slice(idx + 1)];
1335
+ await this.write(next);
1336
+ return next;
1337
+ }
1338
+ /** Whole-file replace. Prefer {@link record} for normal flow. */
1339
+ async write(runs) {
1340
+ const shape = { runs };
1341
+ await this.fs.writeFile(this.path, stringify(shape));
1342
+ }
1343
+ };
1344
+ var SYNTHESIS_ROLE_TAG = "role:synthesis";
1345
+ var ATOM_FRONTMATTER = z.object({
1346
+ schema: z.string().optional().catch(void 0),
1347
+ slug: z.string().optional().catch(void 0),
1348
+ title: z.string().optional().catch(void 0),
1349
+ sources: z.array(z.string()).optional().catch(void 0),
1350
+ confidence: z.number().optional().catch(void 0),
1351
+ tags: z.array(z.string()).optional().catch(void 0),
1352
+ supersedes: z.array(z.string()).optional().catch(void 0),
1353
+ metadata: z.object({
1354
+ corpus: z.object({ status: z.string().optional().catch(void 0) }).loose().optional().catch(void 0)
1355
+ }).loose().optional().catch(void 0)
1356
+ }).loose();
1357
+ async function readEntries(fs) {
1358
+ let rels;
1359
+ try {
1360
+ rels = await fs.walk("entries");
1361
+ } catch {
1362
+ return [];
1363
+ }
1364
+ const out = [];
1365
+ for (const rel of rels) {
1366
+ if (!rel.endsWith(".md")) continue;
1367
+ const path = `entries/${rel}`;
1368
+ let parsed;
1369
+ try {
1370
+ parsed = matter6(await fs.readFile(path));
1371
+ } catch {
1372
+ continue;
1373
+ }
1374
+ const fm = ATOM_FRONTMATTER.parse(parsed.data);
1375
+ if (fm.schema !== "knowledge.entry/v1") continue;
1376
+ const tags = fm.tags ?? [];
1377
+ out.push({
1378
+ slug: fm.slug ?? path,
1379
+ title: fm.title ?? "",
1380
+ body: parsed.content.trim(),
1381
+ confidence: fm.confidence ?? 0,
1382
+ tags,
1383
+ supersedes: fm.supersedes ?? [],
1384
+ path,
1385
+ archived: fm.metadata?.corpus?.status === "archived",
1386
+ isSynthesis: tags.includes(SYNTHESIS_ROLE_TAG)
1387
+ });
1388
+ }
1389
+ return out;
1390
+ }
1391
+ async function currentLensAtoms(fs, lens) {
1392
+ const aspectTag = lensAspectTag(lens);
1393
+ const entries = await readEntries(fs);
1394
+ const superseded = /* @__PURE__ */ new Set();
1395
+ for (const e of entries) for (const s of e.supersedes) superseded.add(s);
1396
+ return entries.filter(
1397
+ (e) => !e.archived && !e.isSynthesis && e.tags.includes(aspectTag) && !superseded.has(e.slug)
1398
+ ).sort((a, b) => b.confidence - a.confidence).map((e) => ({ slug: e.slug, title: e.title, body: e.body }));
1399
+ }
1400
+ function defaultSynthesisPath(lens) {
1401
+ return `entries/summaries/${lensAspect(lens)}-knowledge.md`;
1402
+ }
1403
+ async function lensSynthesisStale(fs, lens) {
1404
+ const atoms = await currentLensAtoms(fs, lens);
1405
+ const atomSlugs = new Set(atoms.map((a) => a.slug));
1406
+ const path = lens.synthesisPath ?? defaultSynthesisPath(lens);
1407
+ if (!await fs.exists(path)) {
1408
+ return { stale: atoms.length > 0, reason: atoms.length > 0 ? "missing" : "fresh", atomCount: atoms.length };
1409
+ }
1410
+ let recorded = [];
1411
+ try {
1412
+ const fm = ATOM_FRONTMATTER.parse(matter6(await fs.readFile(path)).data);
1413
+ recorded = fm.sources ?? [];
1414
+ } catch {
1415
+ return { stale: true, reason: "drifted", atomCount: atoms.length };
1416
+ }
1417
+ const recordedSet = new Set(recorded);
1418
+ const same = recordedSet.size === atomSlugs.size && [...atomSlugs].every((s) => recordedSet.has(s));
1419
+ return {
1420
+ stale: !same,
1421
+ reason: same ? "fresh" : "drifted",
1422
+ atomCount: atoms.length
1423
+ };
1424
+ }
1425
+ async function synthesizeLens(opts) {
1426
+ const { fs, clock, synthesizer, lens } = opts;
1427
+ const aspect = lensAspect(lens);
1428
+ const entries = await readEntries(fs);
1429
+ const aspectTag = lensAspectTag(lens);
1430
+ const considered = entries.filter(
1431
+ (e) => !e.archived && !e.isSynthesis && e.tags.includes(aspectTag)
1432
+ ).length;
1433
+ const atoms = await currentLensAtoms(fs, lens);
1434
+ if (atoms.length === 0) {
1435
+ return { lensId: lens.id, aspect, atomsConsidered: considered, atomsUsed: 0, wrote: false };
1436
+ }
1437
+ const body = await synthesizer.synthesize({ aspect, label: lens.label, atoms });
1438
+ const path = lens.synthesisPath ?? defaultSynthesisPath(lens);
1439
+ await fs.writeFile(path, serializeSynthesis(body, lens, atoms, clock));
1440
+ return {
1441
+ lensId: lens.id,
1442
+ aspect,
1443
+ atomsConsidered: considered,
1444
+ atomsUsed: atoms.length,
1445
+ wrote: true,
1446
+ path
1447
+ };
1448
+ }
1449
+ function serializeSynthesis(body, lens, atoms, clock) {
1450
+ const now = clock.now().toISOString();
1451
+ const slug = `${lensAspect(lens)}-knowledge`;
1452
+ const fm = {
1453
+ schema: "knowledge.entry/v1",
1454
+ slug,
1455
+ kind: "summary",
1456
+ title: `${lens.label} \u2014 current view`,
1457
+ updated_at: now,
1458
+ // Provenance: the atoms this synthesis consolidates (derivedFrom edges).
1459
+ sources: atoms.map((a) => a.slug),
1460
+ confidence: 0.8,
1461
+ // Faceted aspect tag + the synthesis role marker (kept verbatim — both are
1462
+ // AIP-10 facet structure, not plain tags, so they bypass the topic sanitizer).
1463
+ tags: [lensAspectTag(lens), SYNTHESIS_ROLE_TAG],
1464
+ metadata: {
1465
+ corpus: {
1466
+ status: "active",
1467
+ promotionMode: "lens-synthesis",
1468
+ promotedAt: now,
1469
+ lens: lens.id
1470
+ }
1471
+ }
1472
+ };
1473
+ const trimmed = body.trim();
1474
+ return matter6.stringify(trimmed.startsWith("\n") ? trimmed : "\n" + trimmed, fm);
1475
+ }
1476
+ function buildSynthesisPrompt(input) {
1477
+ const atomBlock = input.atoms.map((a, i) => `### Atom ${i + 1}: ${a.title}
1478
+ ${a.body}`).join("\n\n");
1479
+ return `You consolidate the CURRENT knowledge of one aspect into a single living document for an AI operator. You are given the current (non-superseded) atoms \u2014 each a durable insight already extracted. Earlier reversed decisions have already been removed, so treat every atom as currently true.
1480
+
1481
+ ASPECT: ${input.aspect} (${input.label})
1482
+
1483
+ Write a coherent, well-structured markdown document that:
1484
+ - Synthesizes the atoms into a unified current view \u2014 not a list, a narrative the operator can act on.
1485
+ - Resolves overlaps; group related atoms under headings.
1486
+ - States the CURRENT position plainly. Do not hedge with "previously" / "it was decided" \u2014 this is the present truth.
1487
+ - Stays grounded ONLY in the atoms; invent nothing.
1488
+ - Writes in ENGLISH.
1489
+
1490
+ CURRENT ATOMS:
1491
+ ${atomBlock}
1492
+
1493
+ Return ONLY the markdown document body (no frontmatter, no code fence).`;
1494
+ }
1205
1495
  var ANTHROPIC_RESPONSE = z.object({
1206
1496
  content: z.array(
1207
1497
  z.object({ type: z.string(), text: z.string().optional() }).loose()
@@ -2510,6 +2800,20 @@ var CorpusIndexer = class {
2510
2800
  let removed = 0;
2511
2801
  let skipped = 0;
2512
2802
  let chunkCount = 0;
2803
+ let sourcesPushed = 0;
2804
+ if (this.opts.writer.pushSource) {
2805
+ for (const source of snapshot.sources) {
2806
+ const sourceId = source.frontmatter.id;
2807
+ if (typeof sourceId !== "string") continue;
2808
+ await this.opts.writer.pushSource({
2809
+ sourceId,
2810
+ sourcePath: source.path,
2811
+ title: typeof source.frontmatter.title === "string" ? source.frontmatter.title : void 0,
2812
+ sourceFrontmatter: source.frontmatter
2813
+ });
2814
+ sourcesPushed++;
2815
+ }
2816
+ }
2513
2817
  for (const entry of snapshot.entries) {
2514
2818
  const status = readStatus(entry);
2515
2819
  if (status === "active") {
@@ -2526,7 +2830,7 @@ var CorpusIndexer = class {
2526
2830
  skipped++;
2527
2831
  }
2528
2832
  }
2529
- return { pushed, removed, skipped, chunkCount };
2833
+ return { pushed, removed, skipped, chunkCount, sourcesPushed };
2530
2834
  }
2531
2835
  /**
2532
2836
  * Re-sync a single entry by slug. The lifecycle's `promote`
@@ -2572,7 +2876,10 @@ var CorpusIndexer = class {
2572
2876
  confidence: entry.frontmatter.confidence,
2573
2877
  tags: entry.frontmatter.tags,
2574
2878
  ...corpus
2575
- }
2879
+ },
2880
+ // Full frontmatter for a graph-projection writer (relation arrays the
2881
+ // flattened entryMetadata drops). Vector engines ignore it.
2882
+ entryFrontmatter: entry.frontmatter
2576
2883
  });
2577
2884
  return chunks.length;
2578
2885
  }
@@ -3089,7 +3396,7 @@ var PlaybookLifecycle = class {
3089
3396
  async writeWith(playbook, patch) {
3090
3397
  const writer = new CorpusWorkspaceWriter({ fs: this.opts.fs });
3091
3398
  const nextFm = patch({ ...playbook.file.frontmatter });
3092
- const nextContent = matter.stringify(
3399
+ const nextContent = matter6.stringify(
3093
3400
  playbook.body.startsWith("\n") ? playbook.body : "\n" + playbook.body,
3094
3401
  nextFm
3095
3402
  );
@@ -3257,7 +3564,7 @@ var PlaybookEvaluator = class {
3257
3564
  note: `n=${metrics.sampleSize} winRate=${metrics.winRateVsBaseline.toFixed(3)}`
3258
3565
  })
3259
3566
  );
3260
- const content = matter.stringify(
3567
+ const content = matter6.stringify(
3261
3568
  playbook.body.startsWith("\n") ? playbook.body : "\n" + playbook.body,
3262
3569
  fm
3263
3570
  );
@@ -3296,6 +3603,6 @@ function joinPath5(a, b) {
3296
3603
  var SPEC_NAME = "agentcorpus/v1";
3297
3604
  var SPEC_VERSION = "0.1.0-alpha";
3298
3605
 
3299
- export { ANY_REF, ClaudeDistiller, ConversationImporter, CorpusEventEmitter, CorpusIndexer, CorpusLinter, CorpusPromoter, CorpusValidator, CorpusVersionConflictError, CorpusWorkspaceReader, CorpusWorkspaceWriter, DEFAULT_TRANSITIONS, DistillRunner, EMPTY_SELECTOR, IllegalPlaybookTransitionError, IllegalTransitionError, ImporterRunner, KbMigrationImporter, LocalFilesImporter, MemFs, OperatorOverlayResolver, OverlayFs, PlaybookEvaluator, PlaybookLifecycle, PlaybookNotFoundError, PlaybookRegistry, PromoteRejectedError, ReadOnlyFs, ReviewerTrackRecord, SPEC_NAME, SPEC_VERSION, StackResolver, SyncRunner, WELL_KNOWN_AXES, WHITEOUT_SUFFIX, WebImporter, aggregateReviewerScores, appendAttestation, assertTransition, buildDistillPrompt, buildOverlayFromStack, canTransition, capabilityAxis, chunkText, compileLegacyPlaybookBinding, computeReviewerCalibration, createAxisRegistry, createDistillRegistry, enumerateWindowRefs, evaluateAccess, evaluateCapability, evaluateGate, extractAutoPromoteConfig, flattenPackRefs, identityAxis, isEmptySelector, isEntrySlug, isSourceSlug, makeAttestation, matchAttachmentRefs, matchAttachments, matchesLanguageFilter, matchesSelector, normalizeLanguageTag, parseItems, parseSelectorFrontmatter, parseWindowRef, partitionStackRefs, pearsonCorrelation, positionAxis, prefixedRefNormalizer, readAccessModes, readAccessSpec, readAttestations, readEntryLanguage, readOperatorLocale, readWorkspaceDefaultLanguage, renderOverlays, resolveLanguageFilter, roleAxis, runDistill, scanDistilledSourceIds, slugify, transitionGraphFromCollection, uniqueSlug, windowRef, windowSlug };
3606
+ export { ANY_REF, ClaudeDistiller, ConversationImporter, CorpusEventEmitter, CorpusIndexer, CorpusLinter, CorpusPromoter, CorpusValidator, CorpusVersionConflictError, CorpusWorkspaceReader, CorpusWorkspaceWriter, DEFAULT_TRANSITIONS, DISTILL_INDEX_PATH, DistillIndex, DistillRunner, EMPTY_SELECTOR, IllegalPlaybookTransitionError, IllegalTransitionError, ImporterRunner, KbMigrationImporter, LocalFilesImporter, MemFs, OperatorOverlayResolver, OverlayFs, PlaybookEvaluator, PlaybookLifecycle, PlaybookNotFoundError, PlaybookRegistry, PromoteRejectedError, ReadOnlyFs, ReviewerTrackRecord, SPEC_NAME, SPEC_VERSION, SYNTHESIS_ROLE_TAG, StackResolver, SyncRunner, WELL_KNOWN_AXES, WHITEOUT_SUFFIX, WebImporter, aggregateReviewerScores, appendAttestation, assertTransition, buildDistillPrompt, buildOverlayFromStack, buildSynthesisPrompt, canTransition, capabilityAxis, chunkText, compileLegacyPlaybookBinding, computeReviewerCalibration, createAxisRegistry, createDistillRegistry, currentLensAtoms, defaultSynthesisPath, distillFromImporter, enumerateWindowRefs, evaluateAccess, evaluateCapability, evaluateGate, extractAutoPromoteConfig, flattenPackRefs, identityAxis, isEmptySelector, isEntrySlug, isSourceSlug, lensAspect, lensAspectTag, lensSynthesisStale, makeAttestation, matchAttachmentRefs, matchAttachments, matchesLanguageFilter, matchesSelector, modelDistiller, normalizeLanguageTag, parseItems, parseSelectorFrontmatter, parseWindowRef, partitionStackRefs, pearsonCorrelation, positionAxis, prefixedRefNormalizer, readAccessModes, readAccessSpec, readAttestations, readEntryLanguage, readOperatorLocale, readWorkspaceDefaultLanguage, renderOverlays, resolveLanguageFilter, roleAxis, runDistill, scanDistilledSourceIds, slugify, synthesizeLens, transitionGraphFromCollection, uniqueSlug, windowRef, windowSlug };
3300
3607
  //# sourceMappingURL=index.mjs.map
3301
3608
  //# sourceMappingURL=index.mjs.map