@aeptus/aexeo-emdash 0.1.2 → 0.3.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.
@@ -5,7 +5,7 @@ var __export = (target, all) => {
5
5
  };
6
6
 
7
7
  // src/adapter.ts
8
- function contentItemToEmdashDocument(content) {
8
+ function adaptContentItem(content) {
9
9
  const route = deriveRoute(content);
10
10
  const title = stringOrEmpty(
11
11
  content.seo?.title ?? content.data["title"] ?? content.slug ?? content.id
@@ -29,7 +29,16 @@ function contentItemToEmdashDocument(content) {
29
29
  if (body !== null) {
30
30
  document.body = body;
31
31
  }
32
- return document;
32
+ return {
33
+ document,
34
+ meta: {
35
+ id: content.id,
36
+ collection: content.type,
37
+ slug: content.slug,
38
+ status: content.status,
39
+ title
40
+ }
41
+ };
33
42
  }
34
43
  function deriveRoute(content) {
35
44
  if (typeof content.slug === "string" && content.slug.length > 0) {
@@ -65,9 +74,11 @@ function isPortableTextArray(value) {
65
74
 
66
75
  // src/plugin.ts
67
76
  async function handleAfterSaveConfigured(event, ctx, evaluator) {
68
- const document = contentItemToEmdashDocument(event.content);
77
+ const adapted = adaptContentItem(event.content);
78
+ const document = adapted.document;
69
79
  const { kv, log } = ctx;
70
- await kv.set(documentKey(document.route), document);
80
+ const stored = { document, meta: adapted.meta };
81
+ await kv.set(documentKey(document.route), stored);
71
82
  const result = await evaluator([document]);
72
83
  if (!result.ok) {
73
84
  log?.error?.(`afterSave evaluator failure (${result.reason})`, {
@@ -94,6 +105,7 @@ async function evaluateAndPersistAll(ctx, options) {
94
105
  errors: []
95
106
  };
96
107
  const documents = [];
108
+ const adaptedByRoute = /* @__PURE__ */ new Map();
97
109
  const documentRoutes = /* @__PURE__ */ new Set();
98
110
  for (const collection of collections) {
99
111
  let cursor;
@@ -104,9 +116,13 @@ async function evaluateAndPersistAll(ctx, options) {
104
116
  ...cursor === void 0 ? {} : { cursor }
105
117
  });
106
118
  for (const item of page.items) {
107
- const document = contentItemToEmdashDocument(item);
108
- documents.push(document);
109
- documentRoutes.add(document.route);
119
+ const adapted = adaptContentItem(item);
120
+ documents.push(adapted.document);
121
+ documentRoutes.add(adapted.document.route);
122
+ adaptedByRoute.set(adapted.document.route, {
123
+ document: adapted.document,
124
+ meta: adapted.meta
125
+ });
110
126
  }
111
127
  cursor = page.hasMore ? page.cursor : void 0;
112
128
  } catch (err) {
@@ -117,8 +133,8 @@ async function evaluateAndPersistAll(ctx, options) {
117
133
  } while (cursor !== void 0);
118
134
  }
119
135
  summary.documentsScanned = documents.length;
120
- for (const document of documents) {
121
- await kv.set(documentKey(document.route), document);
136
+ for (const stored of adaptedByRoute.values()) {
137
+ await kv.set(documentKey(stored.document.route), stored);
122
138
  }
123
139
  const result = await options.evaluator(documents);
124
140
  if (!result.ok) {
@@ -153,9 +169,39 @@ function documentKey(route) {
153
169
  const normalized = route === "" || route === "/" ? "/" : route;
154
170
  return `document:${normalized}`;
155
171
  }
172
+ var FACTS_KEY = "facts:current";
173
+ async function readStoredFacts(kv) {
174
+ const stored = await kv.get(FACTS_KEY);
175
+ return stored === void 0 ? null : stored;
176
+ }
156
177
  async function readAllDocuments(kv) {
178
+ return (await readAllStoredDocuments(kv)).map((s) => s.document);
179
+ }
180
+ async function readAllStoredDocuments(kv) {
157
181
  const entries = await kv.list("document:");
158
- return entries.map((entry) => entry.value).filter((value) => value !== null);
182
+ const out = [];
183
+ for (const entry of entries) {
184
+ const value = entry.value;
185
+ if (value === null || typeof value !== "object") continue;
186
+ if ("document" in value && "meta" in value) {
187
+ out.push(value);
188
+ continue;
189
+ }
190
+ if ("route" in value) {
191
+ const document = value;
192
+ out.push({
193
+ document,
194
+ meta: {
195
+ id: document.route,
196
+ collection: "",
197
+ slug: null,
198
+ status: "",
199
+ title: document.title ?? ""
200
+ }
201
+ });
202
+ }
203
+ }
204
+ return out;
159
205
  }
160
206
  async function readFindings(kv, route) {
161
207
  const stored = await kv.get(findingsKey(route));
@@ -172,7 +218,9 @@ __export(aexeo_emdash_bridge_bg_exports, {
172
218
  __wbg_set_wasm: () => __wbg_set_wasm,
173
219
  __wbindgen_init_externref_table: () => __wbindgen_init_externref_table,
174
220
  evaluateDocuments: () => evaluateDocuments,
175
- scoreIntelligence: () => scoreIntelligence
221
+ generateFactsPrompt: () => generateFactsPrompt,
222
+ scoreIntelligence: () => scoreIntelligence,
223
+ validateFactsManifest: () => validateFactsManifest
176
224
  });
177
225
  function evaluateDocuments(documents_json, config_json) {
178
226
  let deferred4_0;
@@ -197,13 +245,13 @@ function evaluateDocuments(documents_json, config_json) {
197
245
  wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
198
246
  }
199
247
  }
200
- function scoreIntelligence(documents_json) {
248
+ function generateFactsPrompt(documents_json) {
201
249
  let deferred3_0;
202
250
  let deferred3_1;
203
251
  try {
204
252
  const ptr0 = passStringToWasm0(documents_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
205
253
  const len0 = WASM_VECTOR_LEN;
206
- const ret = wasm.scoreIntelligence(ptr0, len0);
254
+ const ret = wasm.generateFactsPrompt(ptr0, len0);
207
255
  var ptr2 = ret[0];
208
256
  var len2 = ret[1];
209
257
  if (ret[3]) {
@@ -218,6 +266,52 @@ function scoreIntelligence(documents_json) {
218
266
  wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
219
267
  }
220
268
  }
269
+ function scoreIntelligence(documents_json, manifest_json) {
270
+ let deferred4_0;
271
+ let deferred4_1;
272
+ try {
273
+ const ptr0 = passStringToWasm0(documents_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
274
+ const len0 = WASM_VECTOR_LEN;
275
+ var ptr1 = isLikeNone(manifest_json) ? 0 : passStringToWasm0(manifest_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
276
+ var len1 = WASM_VECTOR_LEN;
277
+ const ret = wasm.scoreIntelligence(ptr0, len0, ptr1, len1);
278
+ var ptr3 = ret[0];
279
+ var len3 = ret[1];
280
+ if (ret[3]) {
281
+ ptr3 = 0;
282
+ len3 = 0;
283
+ throw takeFromExternrefTable0(ret[2]);
284
+ }
285
+ deferred4_0 = ptr3;
286
+ deferred4_1 = len3;
287
+ return getStringFromWasm0(ptr3, len3);
288
+ } finally {
289
+ wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
290
+ }
291
+ }
292
+ function validateFactsManifest(manifest_json, documents_json) {
293
+ let deferred4_0;
294
+ let deferred4_1;
295
+ try {
296
+ const ptr0 = passStringToWasm0(manifest_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
297
+ const len0 = WASM_VECTOR_LEN;
298
+ const ptr1 = passStringToWasm0(documents_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
299
+ const len1 = WASM_VECTOR_LEN;
300
+ const ret = wasm.validateFactsManifest(ptr0, len0, ptr1, len1);
301
+ var ptr3 = ret[0];
302
+ var len3 = ret[1];
303
+ if (ret[3]) {
304
+ ptr3 = 0;
305
+ len3 = 0;
306
+ throw takeFromExternrefTable0(ret[2]);
307
+ }
308
+ deferred4_0 = ptr3;
309
+ deferred4_1 = len3;
310
+ return getStringFromWasm0(ptr3, len3);
311
+ } finally {
312
+ wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
313
+ }
314
+ }
221
315
  function __wbg_Error_960c155d3d49e4c2(arg0, arg1) {
222
316
  const ret = Error(getStringFromWasm0(arg0, arg1));
223
317
  return ret;
@@ -333,11 +427,306 @@ async function evaluateDocuments2(documentsJson, configJson) {
333
427
  ensureInitialized();
334
428
  return evaluateDocuments(documentsJson, configJson);
335
429
  }
336
- async function scoreIntelligence2(documentsJson) {
430
+ async function scoreIntelligence2(documentsJson, manifestJson) {
431
+ ensureInitialized();
432
+ return scoreIntelligence(documentsJson, manifestJson ?? void 0);
433
+ }
434
+ async function generateFactsPrompt2(documentsJson) {
435
+ ensureInitialized();
436
+ return generateFactsPrompt(documentsJson);
437
+ }
438
+ async function validateFactsManifest2(manifestJson, documentsJson) {
337
439
  ensureInitialized();
338
- return scoreIntelligence(documentsJson);
440
+ return validateFactsManifest(manifestJson, documentsJson);
339
441
  }
340
442
 
443
+ // src/data-route.ts
444
+ async function handleDataRoute(ctx, options) {
445
+ let summary = null;
446
+ if (options.refresh) {
447
+ summary = await evaluateAndPersistAll(ctx, {
448
+ collections: options.collections,
449
+ evaluator: options.evaluator
450
+ });
451
+ await persistManifestStateFindings(ctx);
452
+ }
453
+ const payload = await buildFindingsPayload(ctx);
454
+ return { payload, summary };
455
+ }
456
+ async function buildFindingsPayload(ctx) {
457
+ const stored = await readAllStoredDocuments(ctx.kv);
458
+ const documents = /* @__PURE__ */ new Map();
459
+ for (const entry of stored) {
460
+ documents.set(entry.document.route, entry);
461
+ }
462
+ const entries = await ctx.kv.list(
463
+ "findings:"
464
+ );
465
+ const findings = [];
466
+ const sitewide = [];
467
+ const perRoute = /* @__PURE__ */ new Map();
468
+ for (const entry of entries) {
469
+ if (entry.value === null) continue;
470
+ const route = entry.key.replace(/^findings:/, "");
471
+ if (route === "*") {
472
+ sitewide.push(...entry.value.findings);
473
+ continue;
474
+ }
475
+ let bucket = perRoute.get(route);
476
+ if (bucket === void 0) {
477
+ bucket = { findings: [], errors: 0, warnings: 0 };
478
+ perRoute.set(route, bucket);
479
+ }
480
+ for (const finding of entry.value.findings) {
481
+ bucket.findings.push(finding);
482
+ if (finding.severity === "error") bucket.errors += 1;
483
+ else if (finding.severity === "warning") bucket.warnings += 1;
484
+ findings.push({ ...finding, route });
485
+ }
486
+ }
487
+ findings.sort((a, b) => severityRank(a.severity) - severityRank(b.severity));
488
+ const siteUrl = ctx.site?.url ?? "";
489
+ const routes = [];
490
+ for (const [route, bucket] of perRoute) {
491
+ const stored2 = documents.get(route);
492
+ routes.push({
493
+ route,
494
+ title: stored2?.meta.title ?? route,
495
+ status: stored2?.meta.status ?? "",
496
+ collection: stored2?.meta.collection ?? "",
497
+ id: stored2?.meta.id ?? "",
498
+ editUrl: stored2 ? buildEditUrl(stored2.meta) : "",
499
+ publishedUrl: stored2 ? buildPublishedUrl(stored2.meta, route, siteUrl) : "",
500
+ findingCount: bucket.findings.length,
501
+ errorCount: bucket.errors,
502
+ warningCount: bucket.warnings
503
+ });
504
+ }
505
+ routes.sort((a, b) => b.errorCount - a.errorCount || a.route.localeCompare(b.route));
506
+ const cached = await ctx.kv.get(
507
+ MANIFEST_FINDINGS_KEY
508
+ );
509
+ if (cached !== void 0 && cached !== null) {
510
+ sitewide.push(...cached.findings);
511
+ }
512
+ return {
513
+ routes,
514
+ findings,
515
+ totals: {
516
+ routes: routes.length,
517
+ findings: findings.length,
518
+ errors: findings.filter((f) => f.severity === "error").length,
519
+ warnings: findings.filter((f) => f.severity === "warning").length,
520
+ documentsIndexed: documents.size
521
+ },
522
+ sitewideFindings: sitewide
523
+ };
524
+ }
525
+ var MANIFEST_FINDINGS_KEY = "meta:facts-findings";
526
+ async function persistManifestStateFindings(ctx) {
527
+ const findings = await deriveManifestStateFindings(ctx);
528
+ await ctx.kv.set(MANIFEST_FINDINGS_KEY, { findings });
529
+ }
530
+ async function deriveManifestStateFindings(ctx) {
531
+ const manifest = await readStoredFacts(ctx.kv);
532
+ if (manifest === null) {
533
+ return [
534
+ {
535
+ rule_id: "FACTS001",
536
+ message: "No truth manifest authored yet. Open the Truth manifest page to generate an LLM authoring prompt and save your facts.json.",
537
+ severity: "warning",
538
+ path: "",
539
+ line: 0,
540
+ column: 0,
541
+ scope: "sitewide",
542
+ suggestion: null
543
+ }
544
+ ];
545
+ }
546
+ const documents = await readAllDocuments(ctx.kv);
547
+ if (documents.length === 0) {
548
+ return [];
549
+ }
550
+ try {
551
+ const raw = await validateFactsManifest2(
552
+ JSON.stringify(manifest),
553
+ JSON.stringify(documents)
554
+ );
555
+ const result = JSON.parse(raw);
556
+ const out = [];
557
+ if (!result.validation.valid || result.validation.errors.length > 0) {
558
+ out.push({
559
+ rule_id: "FACTS001",
560
+ message: `Truth manifest fails shape validation: ${result.validation.errors.slice(0, 3).join("; ")}`,
561
+ severity: "error",
562
+ path: "",
563
+ line: 0,
564
+ column: 0,
565
+ scope: "sitewide",
566
+ suggestion: null
567
+ });
568
+ }
569
+ const errCount = result.assessment.mismatches.filter(
570
+ (m) => m.severity === "error"
571
+ ).length;
572
+ const warnCount = result.assessment.mismatches.length - errCount;
573
+ if (result.assessment.mismatches.length > 0) {
574
+ out.push({
575
+ rule_id: "FACTS003",
576
+ message: `Truth manifest disagrees with on-page schema.org: ${errCount} errors, ${warnCount} warnings. Open the Truth manifest page to review and refresh.`,
577
+ severity: errCount > 0 ? "error" : "warning",
578
+ path: "",
579
+ line: 0,
580
+ column: 0,
581
+ scope: "sitewide",
582
+ suggestion: null
583
+ });
584
+ }
585
+ return out;
586
+ } catch {
587
+ return [];
588
+ }
589
+ }
590
+ function severityRank(severity) {
591
+ if (severity === "error") return 0;
592
+ if (severity === "warning") return 1;
593
+ return 2;
594
+ }
595
+ function buildEditUrl(meta) {
596
+ if (meta.collection === "" || meta.id === "") return "";
597
+ return `/_emdash/admin/content/${encodeURIComponent(meta.collection)}/${encodeURIComponent(meta.id)}`;
598
+ }
599
+ function buildPublishedUrl(meta, route, siteUrl) {
600
+ if (meta.status !== "published") return "";
601
+ if (siteUrl === "") return "";
602
+ const trimmed = siteUrl.endsWith("/") ? siteUrl.slice(0, -1) : siteUrl;
603
+ return `${trimmed}${route}`;
604
+ }
605
+
606
+ // src/facts-route.ts
607
+ async function handleFactsRoute(ctx) {
608
+ const body = ctx.input ?? {};
609
+ switch (body.kind) {
610
+ case "data":
611
+ return await handleData(ctx);
612
+ case "prompt":
613
+ return await handlePrompt(ctx);
614
+ case "validate":
615
+ return await handleValidate(ctx, body);
616
+ case "save":
617
+ return await handleSave(ctx, body);
618
+ default:
619
+ return {
620
+ error: {
621
+ code: "unknown_kind",
622
+ message: `unknown facts route kind: ${String(body.kind)}`
623
+ }
624
+ };
625
+ }
626
+ }
627
+ async function handleData(ctx) {
628
+ const manifest = await readStoredFacts(ctx.kv);
629
+ return {
630
+ data: {
631
+ manifest,
632
+ // The presence flag lets the React component branch on
633
+ // "show authoring CTA" vs "show 'manifest stored' state" without
634
+ // having to introspect the manifest shape.
635
+ present: manifest !== null
636
+ }
637
+ };
638
+ }
639
+ async function handlePrompt(ctx) {
640
+ const documents = await readAllDocuments(ctx.kv);
641
+ if (documents.length === 0) {
642
+ return {
643
+ error: {
644
+ code: "no_documents",
645
+ message: "no documents indexed yet \u2014 click Refresh on the Findings page first, then come back to author the manifest"
646
+ }
647
+ };
648
+ }
649
+ const prompt = await generateFactsPrompt2(JSON.stringify(documents));
650
+ return { data: { prompt } };
651
+ }
652
+ async function handleValidate(ctx, body) {
653
+ if (typeof body.manifest_json !== "string" || body.manifest_json.length === 0) {
654
+ return {
655
+ error: {
656
+ code: "missing_manifest",
657
+ message: "manifest_json field is required"
658
+ }
659
+ };
660
+ }
661
+ const documents = await readAllDocuments(ctx.kv);
662
+ try {
663
+ const raw = await validateFactsManifest2(
664
+ body.manifest_json,
665
+ JSON.stringify(documents)
666
+ );
667
+ return { data: JSON.parse(raw) };
668
+ } catch (error) {
669
+ return {
670
+ error: {
671
+ code: "validate_failed",
672
+ message: error instanceof Error ? error.message : String(error)
673
+ }
674
+ };
675
+ }
676
+ }
677
+ async function handleSave(ctx, body) {
678
+ if (typeof body.manifest_json !== "string" || body.manifest_json.length === 0) {
679
+ return {
680
+ error: {
681
+ code: "missing_manifest",
682
+ message: "manifest_json field is required"
683
+ }
684
+ };
685
+ }
686
+ const documents = await readAllDocuments(ctx.kv);
687
+ let validation;
688
+ try {
689
+ const raw = await validateFactsManifest2(
690
+ body.manifest_json,
691
+ JSON.stringify(documents)
692
+ );
693
+ const parsed2 = JSON.parse(raw);
694
+ validation = parsed2.validation;
695
+ } catch (error) {
696
+ return {
697
+ error: {
698
+ code: "validate_failed",
699
+ message: error instanceof Error ? error.message : String(error)
700
+ }
701
+ };
702
+ }
703
+ if (!validation.valid || validation.errors.length > 0) {
704
+ return {
705
+ error: {
706
+ code: "validation_failed",
707
+ message: `manifest does not pass shape validation: ${validation.errors.slice(0, 3).join("; ")}`
708
+ }
709
+ };
710
+ }
711
+ let parsed;
712
+ try {
713
+ parsed = JSON.parse(body.manifest_json);
714
+ } catch (error) {
715
+ return {
716
+ error: {
717
+ code: "parse_failed",
718
+ message: error instanceof Error ? error.message : String(error)
719
+ }
720
+ };
721
+ }
722
+ await ctx.kv.set(FACTS_KEY, parsed);
723
+ await persistManifestStateFindings(ctx);
724
+ return { data: { saved: true } };
725
+ }
726
+
727
+ // src/version.ts
728
+ var PACKAGE_VERSION = "0.3.0";
729
+
341
730
  // src/configured.ts
342
731
  import { definePlugin } from "emdash";
343
732
  var inProcessEvaluator = async (documents) => {
@@ -361,7 +750,7 @@ function createPlugin(options = {}) {
361
750
  const collections = options.collections === void 0 ? DEFAULT_COLLECTIONS : [...options.collections];
362
751
  return definePlugin({
363
752
  id: "aexeo-seogeo",
364
- version: "0.0.1",
753
+ version: PACKAGE_VERSION,
365
754
  capabilities: ["read:content"],
366
755
  hooks: {
367
756
  // afterSave processes one saved document at a time — collections
@@ -375,6 +764,34 @@ function createPlugin(options = {}) {
375
764
  // every request handles the same set without re-reading options.
376
765
  admin: {
377
766
  handler: (ctx) => handleAdminRoute(ctx, collections)
767
+ },
768
+ // JSON data endpoint for the React adminEntry. Two routes:
769
+ // POST /_emdash/api/plugins/aexeo-seogeo/data — read current findings
770
+ // POST /_emdash/api/plugins/aexeo-seogeo/refresh — sweep + read
771
+ // Returning JSON (not Block Kit blocks) lets the React
772
+ // <Findings/> component render proper <a href> links to the
773
+ // emdash edit page and the public site, which Block Kit can't
774
+ // express in any element type as of emdash 0.8.0.
775
+ data: {
776
+ handler: async (ctx) => (await handleDataRoute(ctx, {
777
+ collections,
778
+ evaluator: inProcessEvaluator,
779
+ refresh: false
780
+ })).payload
781
+ },
782
+ refresh: {
783
+ handler: (ctx) => handleDataRoute(ctx, {
784
+ collections,
785
+ evaluator: inProcessEvaluator,
786
+ refresh: true
787
+ })
788
+ },
789
+ // /facts route serves the truth-manifest authoring UI. It
790
+ // multiplexes four operations (data / prompt / validate / save)
791
+ // onto one POST endpoint via a "kind" body field — see
792
+ // facts-route.ts for the full contract.
793
+ facts: {
794
+ handler: (ctx) => handleFactsRoute(ctx)
378
795
  }
379
796
  },
380
797
  admin: {
@@ -385,7 +802,8 @@ function createPlugin(options = {}) {
385
802
  // duplicate "SEO findings" sidebar entries — that was the
386
803
  // visible 0.1.0 / 0.1.1 bug fixed in 0.1.2.
387
804
  { path: "/findings", label: "SEO findings" },
388
- { path: "/document", label: "Document SEO" }
805
+ { path: "/document", label: "Document SEO" },
806
+ { path: "/facts", label: "Truth manifest" }
389
807
  ],
390
808
  widgets: [
391
809
  { id: "seogeo-score", size: "third", title: "SEO score" }
@@ -580,14 +998,16 @@ async function renderScoreWidget(ctx) {
580
998
  ]
581
999
  };
582
1000
  }
583
- const score = await scoreLocally(documents);
1001
+ const facts = await readStoredFacts(ctx.kv);
1002
+ const score = await scoreLocally(documents, facts);
1003
+ const truthLabel = formatTruthLabel(score);
584
1004
  const blocks = [
585
1005
  {
586
1006
  type: "stats",
587
1007
  items: [
588
1008
  { label: "Overall", value: `${score.overall_score}` },
589
1009
  { label: "Citation", value: `${score.citation_readiness_score}` },
590
- { label: "Truth", value: `${score.truth_consistency_score}` },
1010
+ { label: truthLabel, value: `${score.truth_consistency_score}` },
591
1011
  { label: "Answers", value: `${score.answer_pack_score}` }
592
1012
  ]
593
1013
  }
@@ -604,10 +1024,25 @@ async function renderScoreWidget(ctx) {
604
1024
  }
605
1025
  return { blocks };
606
1026
  }
607
- async function scoreLocally(documents) {
608
- const raw = await scoreIntelligence2(JSON.stringify(documents));
1027
+ async function scoreLocally(documents, manifest = null) {
1028
+ const manifestJson = manifest === null ? null : JSON.stringify(manifest);
1029
+ const raw = await scoreIntelligence2(JSON.stringify(documents), manifestJson);
609
1030
  return JSON.parse(raw);
610
1031
  }
1032
+ function formatTruthLabel(score) {
1033
+ switch (score.structured_truth_source) {
1034
+ case "schema_and_manifest":
1035
+ return "Truth (manifest+schema)";
1036
+ case "manifest":
1037
+ return "Truth (manifest only)";
1038
+ case "schema":
1039
+ return "Truth (schema only)";
1040
+ case "none":
1041
+ return "Truth (no signal)";
1042
+ default:
1043
+ return "Truth";
1044
+ }
1045
+ }
611
1046
  function topBlockersLine(score) {
612
1047
  const top = score.blockers.slice(0, 3).map((b) => b.message);
613
1048
  if (top.length === 0) return "No blockers identified.";
@@ -0,0 +1,49 @@
1
+ import type { EvaluatorFn, RefreshSummary, SandboxCtx } from "./plugin.js";
2
+ import type { Finding } from "./types.js";
3
+ export interface FindingsPayload {
4
+ routes: RouteSummary[];
5
+ findings: FindingRow[];
6
+ totals: {
7
+ routes: number;
8
+ findings: number;
9
+ errors: number;
10
+ warnings: number;
11
+ documentsIndexed: number;
12
+ };
13
+ sitewideFindings: Finding[];
14
+ }
15
+ export interface RouteSummary {
16
+ route: string;
17
+ title: string;
18
+ status: string;
19
+ collection: string;
20
+ id: string;
21
+ editUrl: string;
22
+ publishedUrl: string;
23
+ findingCount: number;
24
+ errorCount: number;
25
+ warningCount: number;
26
+ }
27
+ export interface FindingRow {
28
+ route: string;
29
+ rule_id: string;
30
+ severity: string;
31
+ message: string;
32
+ path: string;
33
+ line: number;
34
+ column: number;
35
+ scope: string;
36
+ suggestion: string | null;
37
+ }
38
+ interface DataRouteOptions {
39
+ collections: readonly string[];
40
+ evaluator: EvaluatorFn;
41
+ refresh: boolean;
42
+ }
43
+ export declare function handleDataRoute(ctx: SandboxCtx, options: DataRouteOptions): Promise<{
44
+ payload: FindingsPayload;
45
+ summary: RefreshSummary | null;
46
+ }>;
47
+ export declare function persistManifestStateFindings(ctx: SandboxCtx): Promise<void>;
48
+ export {};
49
+ //# sourceMappingURL=data-route.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-route.d.ts","sourceRoot":"","sources":["../src/data-route.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,UAAU,EAEX,MAAM,aAAa,CAAC;AAQrB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAM1C,MAAM,WAAW,eAAe;IAG9B,MAAM,EAAE,YAAY,EAAE,CAAC;IAIvB,QAAQ,EAAE,UAAU,EAAE,CAAC;IAIvB,MAAM,EAAE;QACN,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC;IAIF,gBAAgB,EAAE,OAAO,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IAGd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IAIX,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,UAAU,gBAAgB;IACxB,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,SAAS,EAAE,WAAW,CAAC;IAIvB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,eAAe,CACnC,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC;IACT,OAAO,EAAE,eAAe,CAAC;IACzB,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;CAChC,CAAC,CAgBD;AAgGD,wBAAsB,4BAA4B,CAChD,GAAG,EAAE,UAAU,GACd,OAAO,CAAC,IAAI,CAAC,CAGf"}
@@ -0,0 +1,7 @@
1
+ import type { SandboxCtx } from "./plugin.js";
2
+ interface RouteContext extends SandboxCtx {
3
+ input?: unknown;
4
+ }
5
+ export declare function handleFactsRoute(ctx: RouteContext): Promise<unknown>;
6
+ export {};
7
+ //# sourceMappingURL=facts-route.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"facts-route.d.ts","sourceRoot":"","sources":["../src/facts-route.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAa9C,UAAU,YAAa,SAAQ,UAAU;IACvC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAmB1E"}
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@ export interface ConfiguredPluginDescriptor {
4
4
  id: string;
5
5
  version: string;
6
6
  entrypoint: string;
7
+ adminEntry?: string;
7
8
  options: Record<string, unknown>;
8
9
  capabilities: readonly string[];
9
10
  allowedHosts?: readonly string[];
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,yBAAyB,EACzB,sBAAsB,GACvB,MAAM,cAAc,CAAC;AAWtB,MAAM,WAAW,0BAA0B;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,UAAU,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACvD,YAAY,EAAE,SAAS;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACxE;AAED,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACjC;AAED,wBAAgB,YAAY,CAC1B,OAAO,GAAE,mBAAwB,GAChC,0BAA0B,CAsC5B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,yBAAyB,EACzB,sBAAsB,GACvB,MAAM,cAAc,CAAC;AAYtB,MAAM,WAAW,0BAA0B;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IAOnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,UAAU,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACvD,YAAY,EAAE,SAAS;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACxE;AAED,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACjC;AAED,wBAAgB,YAAY,CAC1B,OAAO,GAAE,mBAAwB,GAChC,0BAA0B,CA+C5B"}