@aeptus/aexeo-emdash 0.2.0 → 0.4.0

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.
@@ -73,7 +73,7 @@ function isPortableTextArray(value) {
73
73
  }
74
74
 
75
75
  // src/plugin.ts
76
- async function handleAfterSaveConfigured(event, ctx, evaluator) {
76
+ async function handleAfterSaveConfigured(event, ctx, evaluator, suppressionFilter) {
77
77
  const adapted = adaptContentItem(event.content);
78
78
  const document = adapted.document;
79
79
  const { kv, log } = ctx;
@@ -89,14 +89,16 @@ async function handleAfterSaveConfigured(event, ctx, evaluator) {
89
89
  const pageFindings = result.findings.filter(
90
90
  (finding) => finding.scope === "page"
91
91
  );
92
+ const filtered = suppressionFilter === void 0 ? pageFindings : suppressionFilter.apply(document.route, pageFindings);
92
93
  await kv.set(findingsKey(document.route), {
93
94
  route: document.route,
94
- findings: pageFindings
95
+ findings: filtered
95
96
  });
96
97
  }
97
98
  var DEFAULT_COLLECTIONS = ["posts", "pages"];
98
99
  async function evaluateAndPersistAll(ctx, options) {
99
100
  const collections = options.collections ?? DEFAULT_COLLECTIONS;
101
+ const suppressionFilter = options.suppressionFilter;
100
102
  const { kv, log } = ctx;
101
103
  const summary = {
102
104
  documentsScanned: 0,
@@ -154,11 +156,14 @@ async function evaluateAndPersistAll(ctx, options) {
154
156
  list.push(finding);
155
157
  findingsByRoute.set(bucket, list);
156
158
  }
159
+ let totalAfterSuppression = 0;
157
160
  for (const [route, findings] of findingsByRoute) {
158
- await kv.set(findingsKey(route), { route, findings });
161
+ const filtered = suppressionFilter === void 0 ? findings : suppressionFilter.apply(route, findings);
162
+ await kv.set(findingsKey(route), { route, findings: filtered });
159
163
  summary.routesUpdated += 1;
164
+ totalAfterSuppression += filtered.length;
160
165
  }
161
- summary.totalFindings = result.findings.length;
166
+ summary.totalFindings = totalAfterSuppression;
162
167
  return summary;
163
168
  }
164
169
  function findingsKey(route) {
@@ -169,6 +174,11 @@ function documentKey(route) {
169
174
  const normalized = route === "" || route === "/" ? "/" : route;
170
175
  return `document:${normalized}`;
171
176
  }
177
+ var FACTS_KEY = "facts:current";
178
+ async function readStoredFacts(kv) {
179
+ const stored = await kv.get(FACTS_KEY);
180
+ return stored === void 0 ? null : stored;
181
+ }
172
182
  async function readAllDocuments(kv) {
173
183
  return (await readAllStoredDocuments(kv)).map((s) => s.document);
174
184
  }
@@ -206,97 +216,6 @@ async function readFindings(kv, route) {
206
216
  return stored.findings;
207
217
  }
208
218
 
209
- // src/data-route.ts
210
- async function handleDataRoute(ctx, options) {
211
- let summary = null;
212
- if (options.refresh) {
213
- summary = await evaluateAndPersistAll(ctx, {
214
- collections: options.collections,
215
- evaluator: options.evaluator
216
- });
217
- }
218
- const payload = await buildFindingsPayload(ctx);
219
- return { payload, summary };
220
- }
221
- async function buildFindingsPayload(ctx) {
222
- const stored = await readAllStoredDocuments(ctx.kv);
223
- const documents = /* @__PURE__ */ new Map();
224
- for (const entry of stored) {
225
- documents.set(entry.document.route, entry);
226
- }
227
- const entries = await ctx.kv.list(
228
- "findings:"
229
- );
230
- const findings = [];
231
- const sitewide = [];
232
- const perRoute = /* @__PURE__ */ new Map();
233
- for (const entry of entries) {
234
- if (entry.value === null) continue;
235
- const route = entry.key.replace(/^findings:/, "");
236
- if (route === "*") {
237
- sitewide.push(...entry.value.findings);
238
- continue;
239
- }
240
- let bucket = perRoute.get(route);
241
- if (bucket === void 0) {
242
- bucket = { findings: [], errors: 0, warnings: 0 };
243
- perRoute.set(route, bucket);
244
- }
245
- for (const finding of entry.value.findings) {
246
- bucket.findings.push(finding);
247
- if (finding.severity === "error") bucket.errors += 1;
248
- else if (finding.severity === "warning") bucket.warnings += 1;
249
- findings.push({ ...finding, route });
250
- }
251
- }
252
- findings.sort((a, b) => severityRank(a.severity) - severityRank(b.severity));
253
- const siteUrl = ctx.site?.url ?? "";
254
- const routes = [];
255
- for (const [route, bucket] of perRoute) {
256
- const stored2 = documents.get(route);
257
- routes.push({
258
- route,
259
- title: stored2?.meta.title ?? route,
260
- status: stored2?.meta.status ?? "",
261
- collection: stored2?.meta.collection ?? "",
262
- id: stored2?.meta.id ?? "",
263
- editUrl: stored2 ? buildEditUrl(stored2.meta) : "",
264
- publishedUrl: stored2 ? buildPublishedUrl(stored2.meta, route, siteUrl) : "",
265
- findingCount: bucket.findings.length,
266
- errorCount: bucket.errors,
267
- warningCount: bucket.warnings
268
- });
269
- }
270
- routes.sort((a, b) => b.errorCount - a.errorCount || a.route.localeCompare(b.route));
271
- return {
272
- routes,
273
- findings,
274
- totals: {
275
- routes: routes.length,
276
- findings: findings.length,
277
- errors: findings.filter((f) => f.severity === "error").length,
278
- warnings: findings.filter((f) => f.severity === "warning").length,
279
- documentsIndexed: documents.size
280
- },
281
- sitewideFindings: sitewide
282
- };
283
- }
284
- function severityRank(severity) {
285
- if (severity === "error") return 0;
286
- if (severity === "warning") return 1;
287
- return 2;
288
- }
289
- function buildEditUrl(meta) {
290
- if (meta.collection === "" || meta.id === "") return "";
291
- return `/_emdash/admin/content/${encodeURIComponent(meta.collection)}/${encodeURIComponent(meta.id)}`;
292
- }
293
- function buildPublishedUrl(meta, route, siteUrl) {
294
- if (meta.status !== "published") return "";
295
- if (siteUrl === "") return "";
296
- const trimmed = siteUrl.endsWith("/") ? siteUrl.slice(0, -1) : siteUrl;
297
- return `${trimmed}${route}`;
298
- }
299
-
300
219
  // wasm/aexeo_emdash_bridge_bg.js
301
220
  var aexeo_emdash_bridge_bg_exports = {};
302
221
  __export(aexeo_emdash_bridge_bg_exports, {
@@ -304,7 +223,9 @@ __export(aexeo_emdash_bridge_bg_exports, {
304
223
  __wbg_set_wasm: () => __wbg_set_wasm,
305
224
  __wbindgen_init_externref_table: () => __wbindgen_init_externref_table,
306
225
  evaluateDocuments: () => evaluateDocuments,
307
- scoreIntelligence: () => scoreIntelligence
226
+ generateFactsPrompt: () => generateFactsPrompt,
227
+ scoreIntelligence: () => scoreIntelligence,
228
+ validateFactsManifest: () => validateFactsManifest
308
229
  });
309
230
  function evaluateDocuments(documents_json, config_json) {
310
231
  let deferred4_0;
@@ -329,13 +250,13 @@ function evaluateDocuments(documents_json, config_json) {
329
250
  wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
330
251
  }
331
252
  }
332
- function scoreIntelligence(documents_json) {
253
+ function generateFactsPrompt(documents_json) {
333
254
  let deferred3_0;
334
255
  let deferred3_1;
335
256
  try {
336
257
  const ptr0 = passStringToWasm0(documents_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
337
258
  const len0 = WASM_VECTOR_LEN;
338
- const ret = wasm.scoreIntelligence(ptr0, len0);
259
+ const ret = wasm.generateFactsPrompt(ptr0, len0);
339
260
  var ptr2 = ret[0];
340
261
  var len2 = ret[1];
341
262
  if (ret[3]) {
@@ -350,6 +271,52 @@ function scoreIntelligence(documents_json) {
350
271
  wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
351
272
  }
352
273
  }
274
+ function scoreIntelligence(documents_json, manifest_json) {
275
+ let deferred4_0;
276
+ let deferred4_1;
277
+ try {
278
+ const ptr0 = passStringToWasm0(documents_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
279
+ const len0 = WASM_VECTOR_LEN;
280
+ var ptr1 = isLikeNone(manifest_json) ? 0 : passStringToWasm0(manifest_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
281
+ var len1 = WASM_VECTOR_LEN;
282
+ const ret = wasm.scoreIntelligence(ptr0, len0, ptr1, len1);
283
+ var ptr3 = ret[0];
284
+ var len3 = ret[1];
285
+ if (ret[3]) {
286
+ ptr3 = 0;
287
+ len3 = 0;
288
+ throw takeFromExternrefTable0(ret[2]);
289
+ }
290
+ deferred4_0 = ptr3;
291
+ deferred4_1 = len3;
292
+ return getStringFromWasm0(ptr3, len3);
293
+ } finally {
294
+ wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
295
+ }
296
+ }
297
+ function validateFactsManifest(manifest_json, documents_json) {
298
+ let deferred4_0;
299
+ let deferred4_1;
300
+ try {
301
+ const ptr0 = passStringToWasm0(manifest_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
302
+ const len0 = WASM_VECTOR_LEN;
303
+ const ptr1 = passStringToWasm0(documents_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
304
+ const len1 = WASM_VECTOR_LEN;
305
+ const ret = wasm.validateFactsManifest(ptr0, len0, ptr1, len1);
306
+ var ptr3 = ret[0];
307
+ var len3 = ret[1];
308
+ if (ret[3]) {
309
+ ptr3 = 0;
310
+ len3 = 0;
311
+ throw takeFromExternrefTable0(ret[2]);
312
+ }
313
+ deferred4_0 = ptr3;
314
+ deferred4_1 = len3;
315
+ return getStringFromWasm0(ptr3, len3);
316
+ } finally {
317
+ wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
318
+ }
319
+ }
353
320
  function __wbg_Error_960c155d3d49e4c2(arg0, arg1) {
354
321
  const ret = Error(getStringFromWasm0(arg0, arg1));
355
322
  return ret;
@@ -465,11 +432,349 @@ async function evaluateDocuments2(documentsJson, configJson) {
465
432
  ensureInitialized();
466
433
  return evaluateDocuments(documentsJson, configJson);
467
434
  }
468
- async function scoreIntelligence2(documentsJson) {
435
+ async function scoreIntelligence2(documentsJson, manifestJson) {
469
436
  ensureInitialized();
470
- return scoreIntelligence(documentsJson);
437
+ return scoreIntelligence(documentsJson, manifestJson ?? void 0);
438
+ }
439
+ async function generateFactsPrompt2(documentsJson) {
440
+ ensureInitialized();
441
+ return generateFactsPrompt(documentsJson);
442
+ }
443
+ async function validateFactsManifest2(manifestJson, documentsJson) {
444
+ ensureInitialized();
445
+ return validateFactsManifest(manifestJson, documentsJson);
471
446
  }
472
447
 
448
+ // src/data-route.ts
449
+ async function handleDataRoute(ctx, options) {
450
+ let summary = null;
451
+ if (options.refresh) {
452
+ summary = await evaluateAndPersistAll(ctx, {
453
+ collections: options.collections,
454
+ evaluator: options.evaluator,
455
+ ...options.suppressionFilter === void 0 ? {} : { suppressionFilter: options.suppressionFilter }
456
+ });
457
+ await persistManifestStateFindings(ctx);
458
+ }
459
+ const payload = await buildFindingsPayload(ctx);
460
+ return { payload, summary };
461
+ }
462
+ async function buildFindingsPayload(ctx) {
463
+ const stored = await readAllStoredDocuments(ctx.kv);
464
+ const documents = /* @__PURE__ */ new Map();
465
+ for (const entry of stored) {
466
+ documents.set(entry.document.route, entry);
467
+ }
468
+ const entries = await ctx.kv.list(
469
+ "findings:"
470
+ );
471
+ const findings = [];
472
+ const sitewide = [];
473
+ const perRoute = /* @__PURE__ */ new Map();
474
+ for (const entry of entries) {
475
+ if (entry.value === null) continue;
476
+ const route = entry.key.replace(/^findings:/, "");
477
+ if (route === "*") {
478
+ sitewide.push(...entry.value.findings);
479
+ continue;
480
+ }
481
+ let bucket = perRoute.get(route);
482
+ if (bucket === void 0) {
483
+ bucket = { findings: [], errors: 0, warnings: 0 };
484
+ perRoute.set(route, bucket);
485
+ }
486
+ for (const finding of entry.value.findings) {
487
+ bucket.findings.push(finding);
488
+ if (finding.severity === "error") bucket.errors += 1;
489
+ else if (finding.severity === "warning") bucket.warnings += 1;
490
+ findings.push({ ...finding, route });
491
+ }
492
+ }
493
+ findings.sort((a, b) => severityRank(a.severity) - severityRank(b.severity));
494
+ const siteUrl = ctx.site?.url ?? "";
495
+ const routes = [];
496
+ for (const [route, bucket] of perRoute) {
497
+ const stored2 = documents.get(route);
498
+ routes.push({
499
+ route,
500
+ title: stored2?.meta.title ?? route,
501
+ status: stored2?.meta.status ?? "",
502
+ collection: stored2?.meta.collection ?? "",
503
+ id: stored2?.meta.id ?? "",
504
+ editUrl: stored2 ? buildEditUrl(stored2.meta) : "",
505
+ publishedUrl: stored2 ? buildPublishedUrl(stored2.meta, route, siteUrl) : "",
506
+ findingCount: bucket.findings.length,
507
+ errorCount: bucket.errors,
508
+ warningCount: bucket.warnings
509
+ });
510
+ }
511
+ routes.sort((a, b) => b.errorCount - a.errorCount || a.route.localeCompare(b.route));
512
+ const cached = await ctx.kv.get(
513
+ MANIFEST_FINDINGS_KEY
514
+ );
515
+ if (cached !== void 0 && cached !== null) {
516
+ sitewide.push(...cached.findings);
517
+ }
518
+ return {
519
+ routes,
520
+ findings,
521
+ totals: {
522
+ routes: routes.length,
523
+ findings: findings.length,
524
+ errors: findings.filter((f) => f.severity === "error").length,
525
+ warnings: findings.filter((f) => f.severity === "warning").length,
526
+ documentsIndexed: documents.size
527
+ },
528
+ sitewideFindings: sitewide
529
+ };
530
+ }
531
+ var MANIFEST_FINDINGS_KEY = "meta:facts-findings";
532
+ async function persistManifestStateFindings(ctx) {
533
+ const findings = await deriveManifestStateFindings(ctx);
534
+ await ctx.kv.set(MANIFEST_FINDINGS_KEY, { findings });
535
+ }
536
+ async function deriveManifestStateFindings(ctx) {
537
+ const manifest = await readStoredFacts(ctx.kv);
538
+ if (manifest === null) {
539
+ return [
540
+ {
541
+ rule_id: "FACTS001",
542
+ message: "No truth manifest authored yet. Open the Truth manifest page to generate an LLM authoring prompt and save your facts.json.",
543
+ severity: "warning",
544
+ path: "",
545
+ line: 0,
546
+ column: 0,
547
+ scope: "sitewide",
548
+ suggestion: null
549
+ }
550
+ ];
551
+ }
552
+ const documents = await readAllDocuments(ctx.kv);
553
+ if (documents.length === 0) {
554
+ return [];
555
+ }
556
+ try {
557
+ const raw = await validateFactsManifest2(
558
+ JSON.stringify(manifest),
559
+ JSON.stringify(documents)
560
+ );
561
+ const result = JSON.parse(raw);
562
+ const out = [];
563
+ if (!result.validation.valid || result.validation.errors.length > 0) {
564
+ out.push({
565
+ rule_id: "FACTS001",
566
+ message: `Truth manifest fails shape validation: ${result.validation.errors.slice(0, 3).join("; ")}`,
567
+ severity: "error",
568
+ path: "",
569
+ line: 0,
570
+ column: 0,
571
+ scope: "sitewide",
572
+ suggestion: null
573
+ });
574
+ }
575
+ const errCount = result.assessment.mismatches.filter(
576
+ (m) => m.severity === "error"
577
+ ).length;
578
+ const warnCount = result.assessment.mismatches.length - errCount;
579
+ if (result.assessment.mismatches.length > 0) {
580
+ out.push({
581
+ rule_id: "FACTS003",
582
+ message: `Truth manifest disagrees with on-page schema.org: ${errCount} errors, ${warnCount} warnings. Open the Truth manifest page to review and refresh.`,
583
+ severity: errCount > 0 ? "error" : "warning",
584
+ path: "",
585
+ line: 0,
586
+ column: 0,
587
+ scope: "sitewide",
588
+ suggestion: null
589
+ });
590
+ }
591
+ return out;
592
+ } catch {
593
+ return [];
594
+ }
595
+ }
596
+ function severityRank(severity) {
597
+ if (severity === "error") return 0;
598
+ if (severity === "warning") return 1;
599
+ return 2;
600
+ }
601
+ function buildEditUrl(meta) {
602
+ if (meta.collection === "" || meta.id === "") return "";
603
+ return `/_emdash/admin/content/${encodeURIComponent(meta.collection)}/${encodeURIComponent(meta.id)}`;
604
+ }
605
+ function buildPublishedUrl(meta, route, siteUrl) {
606
+ if (meta.status !== "published") return "";
607
+ if (siteUrl === "") return "";
608
+ const trimmed = siteUrl.endsWith("/") ? siteUrl.slice(0, -1) : siteUrl;
609
+ return `${trimmed}${route}`;
610
+ }
611
+
612
+ // src/facts-route.ts
613
+ async function handleFactsRoute(ctx) {
614
+ const body = ctx.input ?? {};
615
+ switch (body.kind) {
616
+ case "data":
617
+ return await handleData(ctx);
618
+ case "prompt":
619
+ return await handlePrompt(ctx);
620
+ case "validate":
621
+ return await handleValidate(ctx, body);
622
+ case "save":
623
+ return await handleSave(ctx, body);
624
+ default:
625
+ return {
626
+ error: {
627
+ code: "unknown_kind",
628
+ message: `unknown facts route kind: ${String(body.kind)}`
629
+ }
630
+ };
631
+ }
632
+ }
633
+ async function handleData(ctx) {
634
+ const manifest = await readStoredFacts(ctx.kv);
635
+ return {
636
+ data: {
637
+ manifest,
638
+ // The presence flag lets the React component branch on
639
+ // "show authoring CTA" vs "show 'manifest stored' state" without
640
+ // having to introspect the manifest shape.
641
+ present: manifest !== null
642
+ }
643
+ };
644
+ }
645
+ async function handlePrompt(ctx) {
646
+ const documents = await readAllDocuments(ctx.kv);
647
+ if (documents.length === 0) {
648
+ return {
649
+ error: {
650
+ code: "no_documents",
651
+ message: "no documents indexed yet \u2014 click Refresh on the Findings page first, then come back to author the manifest"
652
+ }
653
+ };
654
+ }
655
+ const prompt = await generateFactsPrompt2(JSON.stringify(documents));
656
+ return { data: { prompt } };
657
+ }
658
+ async function handleValidate(ctx, body) {
659
+ if (typeof body.manifest_json !== "string" || body.manifest_json.length === 0) {
660
+ return {
661
+ error: {
662
+ code: "missing_manifest",
663
+ message: "manifest_json field is required"
664
+ }
665
+ };
666
+ }
667
+ const documents = await readAllDocuments(ctx.kv);
668
+ try {
669
+ const raw = await validateFactsManifest2(
670
+ body.manifest_json,
671
+ JSON.stringify(documents)
672
+ );
673
+ return { data: JSON.parse(raw) };
674
+ } catch (error) {
675
+ return {
676
+ error: {
677
+ code: "validate_failed",
678
+ message: error instanceof Error ? error.message : String(error)
679
+ }
680
+ };
681
+ }
682
+ }
683
+ async function handleSave(ctx, body) {
684
+ if (typeof body.manifest_json !== "string" || body.manifest_json.length === 0) {
685
+ return {
686
+ error: {
687
+ code: "missing_manifest",
688
+ message: "manifest_json field is required"
689
+ }
690
+ };
691
+ }
692
+ const documents = await readAllDocuments(ctx.kv);
693
+ let validation;
694
+ try {
695
+ const raw = await validateFactsManifest2(
696
+ body.manifest_json,
697
+ JSON.stringify(documents)
698
+ );
699
+ const parsed2 = JSON.parse(raw);
700
+ validation = parsed2.validation;
701
+ } catch (error) {
702
+ return {
703
+ error: {
704
+ code: "validate_failed",
705
+ message: error instanceof Error ? error.message : String(error)
706
+ }
707
+ };
708
+ }
709
+ if (!validation.valid || validation.errors.length > 0) {
710
+ return {
711
+ error: {
712
+ code: "validation_failed",
713
+ message: `manifest does not pass shape validation: ${validation.errors.slice(0, 3).join("; ")}`
714
+ }
715
+ };
716
+ }
717
+ let parsed;
718
+ try {
719
+ parsed = JSON.parse(body.manifest_json);
720
+ } catch (error) {
721
+ return {
722
+ error: {
723
+ code: "parse_failed",
724
+ message: error instanceof Error ? error.message : String(error)
725
+ }
726
+ };
727
+ }
728
+ await ctx.kv.set(FACTS_KEY, parsed);
729
+ await persistManifestStateFindings(ctx);
730
+ return { data: { saved: true } };
731
+ }
732
+
733
+ // src/suppressions.ts
734
+ var NOOP_FILTER = {
735
+ apply: (_route, findings) => [...findings]
736
+ };
737
+ function compileSuppressions(rules) {
738
+ if (rules === void 0 || rules.length === 0) {
739
+ return NOOP_FILTER;
740
+ }
741
+ rules.forEach((rule, index) => {
742
+ const hasRoute = rule.routePattern !== void 0 && rule.routePattern.length > 0;
743
+ const hasRuleIds = rule.ruleIds !== void 0 && rule.ruleIds.length > 0;
744
+ if (!hasRoute && !hasRuleIds) {
745
+ throw new Error(
746
+ `seogeoPlugin: suppressions[${index}] is empty \u2014 set routePattern, ruleIds, or both`
747
+ );
748
+ }
749
+ });
750
+ const compiled = rules.map((rule) => ({
751
+ matchRoute: rule.routePattern === void 0 ? matchAlways : globToMatcher(rule.routePattern),
752
+ ruleIds: rule.ruleIds === void 0 || rule.ruleIds.length === 0 ? null : new Set(rule.ruleIds)
753
+ }));
754
+ return {
755
+ apply(route, findings) {
756
+ return findings.filter((finding) => !compiled.some((rule) => {
757
+ if (!rule.matchRoute(route)) return false;
758
+ if (rule.ruleIds !== null && !rule.ruleIds.has(finding.rule_id)) {
759
+ return false;
760
+ }
761
+ return true;
762
+ }));
763
+ }
764
+ };
765
+ }
766
+ var matchAlways = () => true;
767
+ function globToMatcher(pattern) {
768
+ const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&");
769
+ const DOUBLE_STAR_TOKEN = "";
770
+ let body = escaped.replace(/\*\*/g, DOUBLE_STAR_TOKEN).replace(/\*/g, "[^/]*").replace(new RegExp(DOUBLE_STAR_TOKEN, "g"), ".*").replace(/\?/g, "[^/]");
771
+ const re = new RegExp(`^${body}$`);
772
+ return (route) => re.test(route);
773
+ }
774
+
775
+ // src/version.ts
776
+ var PACKAGE_VERSION = "0.4.0";
777
+
473
778
  // src/configured.ts
474
779
  import { definePlugin } from "emdash";
475
780
  var inProcessEvaluator = async (documents) => {
@@ -491,15 +796,21 @@ var inProcessEvaluator = async (documents) => {
491
796
  };
492
797
  function createPlugin(options = {}) {
493
798
  const collections = options.collections === void 0 ? DEFAULT_COLLECTIONS : [...options.collections];
799
+ const suppressionFilter = compileSuppressions(options.suppressions);
494
800
  return definePlugin({
495
801
  id: "aexeo-seogeo",
496
- version: "0.0.1",
802
+ version: PACKAGE_VERSION,
497
803
  capabilities: ["read:content"],
498
804
  hooks: {
499
805
  // afterSave processes one saved document at a time — collections
500
806
  // list isn't needed here. The hook always runs regardless of
501
807
  // which collection the document came from.
502
- "content:afterSave": (event, ctx) => handleAfterSaveConfigured(event, ctx, inProcessEvaluator)
808
+ "content:afterSave": (event, ctx) => handleAfterSaveConfigured(
809
+ event,
810
+ ctx,
811
+ inProcessEvaluator,
812
+ suppressionFilter
813
+ )
503
814
  },
504
815
  routes: {
505
816
  // The Refresh sweep (handleAdminRoute → handleRefresh) is the
@@ -519,15 +830,24 @@ function createPlugin(options = {}) {
519
830
  handler: async (ctx) => (await handleDataRoute(ctx, {
520
831
  collections,
521
832
  evaluator: inProcessEvaluator,
522
- refresh: false
833
+ refresh: false,
834
+ suppressionFilter
523
835
  })).payload
524
836
  },
525
837
  refresh: {
526
838
  handler: (ctx) => handleDataRoute(ctx, {
527
839
  collections,
528
840
  evaluator: inProcessEvaluator,
529
- refresh: true
841
+ refresh: true,
842
+ suppressionFilter
530
843
  })
844
+ },
845
+ // /facts route serves the truth-manifest authoring UI. It
846
+ // multiplexes four operations (data / prompt / validate / save)
847
+ // onto one POST endpoint via a "kind" body field — see
848
+ // facts-route.ts for the full contract.
849
+ facts: {
850
+ handler: (ctx) => handleFactsRoute(ctx)
531
851
  }
532
852
  },
533
853
  admin: {
@@ -538,7 +858,8 @@ function createPlugin(options = {}) {
538
858
  // duplicate "SEO findings" sidebar entries — that was the
539
859
  // visible 0.1.0 / 0.1.1 bug fixed in 0.1.2.
540
860
  { path: "/findings", label: "SEO findings" },
541
- { path: "/document", label: "Document SEO" }
861
+ { path: "/document", label: "Document SEO" },
862
+ { path: "/facts", label: "Truth manifest" }
542
863
  ],
543
864
  widgets: [
544
865
  { id: "seogeo-score", size: "third", title: "SEO score" }
@@ -733,14 +1054,16 @@ async function renderScoreWidget(ctx) {
733
1054
  ]
734
1055
  };
735
1056
  }
736
- const score = await scoreLocally(documents);
1057
+ const facts = await readStoredFacts(ctx.kv);
1058
+ const score = await scoreLocally(documents, facts);
1059
+ const truthLabel = formatTruthLabel(score);
737
1060
  const blocks = [
738
1061
  {
739
1062
  type: "stats",
740
1063
  items: [
741
1064
  { label: "Overall", value: `${score.overall_score}` },
742
1065
  { label: "Citation", value: `${score.citation_readiness_score}` },
743
- { label: "Truth", value: `${score.truth_consistency_score}` },
1066
+ { label: truthLabel, value: `${score.truth_consistency_score}` },
744
1067
  { label: "Answers", value: `${score.answer_pack_score}` }
745
1068
  ]
746
1069
  }
@@ -757,10 +1080,25 @@ async function renderScoreWidget(ctx) {
757
1080
  }
758
1081
  return { blocks };
759
1082
  }
760
- async function scoreLocally(documents) {
761
- const raw = await scoreIntelligence2(JSON.stringify(documents));
1083
+ async function scoreLocally(documents, manifest = null) {
1084
+ const manifestJson = manifest === null ? null : JSON.stringify(manifest);
1085
+ const raw = await scoreIntelligence2(JSON.stringify(documents), manifestJson);
762
1086
  return JSON.parse(raw);
763
1087
  }
1088
+ function formatTruthLabel(score) {
1089
+ switch (score.structured_truth_source) {
1090
+ case "schema_and_manifest":
1091
+ return "Truth (manifest+schema)";
1092
+ case "manifest":
1093
+ return "Truth (manifest only)";
1094
+ case "schema":
1095
+ return "Truth (schema only)";
1096
+ case "none":
1097
+ return "Truth (no signal)";
1098
+ default:
1099
+ return "Truth";
1100
+ }
1101
+ }
764
1102
  function topBlockersLine(score) {
765
1103
  const top = score.blockers.slice(0, 3).map((b) => b.message);
766
1104
  if (top.length === 0) return "No blockers identified.";
@@ -39,10 +39,12 @@ interface DataRouteOptions {
39
39
  collections: readonly string[];
40
40
  evaluator: EvaluatorFn;
41
41
  refresh: boolean;
42
+ suppressionFilter?: import("./suppressions.js").SuppressionFilter;
42
43
  }
43
44
  export declare function handleDataRoute(ctx: SandboxCtx, options: DataRouteOptions): Promise<{
44
45
  payload: FindingsPayload;
45
46
  summary: RefreshSummary | null;
46
47
  }>;
48
+ export declare function persistManifestStateFindings(ctx: SandboxCtx): Promise<void>;
47
49
  export {};
48
50
  //# sourceMappingURL=data-route.d.ts.map