@aeptus/aexeo-emdash 0.9.0 → 0.9.1

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.
Files changed (46) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/INSTALL.md +181 -8
  3. package/README.md +8 -0
  4. package/dist/adapter.d.ts +34 -4
  5. package/dist/adapter.d.ts.map +1 -1
  6. package/dist/admin/Findings.d.ts.map +1 -1
  7. package/dist/admin.js +71 -4
  8. package/dist/assessment-display.d.ts +10 -0
  9. package/dist/assessment-display.d.ts.map +1 -0
  10. package/dist/cms-coverage.d.ts +10 -0
  11. package/dist/cms-coverage.d.ts.map +1 -0
  12. package/dist/configured.d.ts +11 -2
  13. package/dist/configured.d.ts.map +1 -1
  14. package/dist/configured.js +944 -210
  15. package/dist/content-evaluator.d.ts +22 -2
  16. package/dist/content-evaluator.d.ts.map +1 -1
  17. package/dist/content.d.ts +51 -4
  18. package/dist/content.d.ts.map +1 -1
  19. package/dist/content.js +99 -19
  20. package/dist/data-route.d.ts +9 -1
  21. package/dist/data-route.d.ts.map +1 -1
  22. package/dist/findings-view.d.ts +5 -4
  23. package/dist/findings-view.d.ts.map +1 -1
  24. package/dist/index.d.ts +3 -1
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +79 -15
  27. package/dist/inventory.d.ts +9 -1
  28. package/dist/inventory.d.ts.map +1 -1
  29. package/dist/plugin.d.ts +30 -1
  30. package/dist/plugin.d.ts.map +1 -1
  31. package/dist/sandbox-entry.d.ts.map +1 -1
  32. package/dist/sandbox-entry.js +797 -195
  33. package/dist/sidecar.d.ts +2 -0
  34. package/dist/sidecar.d.ts.map +1 -1
  35. package/dist/types.d.ts +15 -0
  36. package/dist/types.d.ts.map +1 -1
  37. package/dist/version.d.ts +1 -1
  38. package/dist/wasm-init.d.ts +5 -1
  39. package/dist/wasm-init.d.ts.map +1 -1
  40. package/package.json +12 -3
  41. package/wasm/aexeo_emdash_bridge.d.ts +12 -1
  42. package/wasm/aexeo_emdash_bridge.js +1 -1
  43. package/wasm/aexeo_emdash_bridge_bg.d.ts +4 -0
  44. package/wasm/aexeo_emdash_bridge_bg.js +73 -11
  45. package/wasm/aexeo_emdash_bridge_bg.wasm +0 -0
  46. package/wasm/aexeo_emdash_bridge_bg.wasm.d.ts +3 -1
package/CHANGELOG.md CHANGED
@@ -6,6 +6,22 @@ and the project follows [Semantic Versioning](https://semver.org/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.9.1] - 2026-11-12
10
+
11
+ ### Added
12
+
13
+ - Support host-provided component, inventory route and locale mappings, and preserve precise CMS source positions when available.
14
+ - Report content assessment coverage and measurements, with opt-in external gate and link observation providers.
15
+
16
+ ### Fixed
17
+
18
+ - Count body findings withheld due to incomplete CMS projections in aggregate telemetry, and test native family coverage against the rule registry.
19
+ - Withhold native page and site rules unless their evidence is observable from the CMS body; preserve explicitly tagged content-preset findings and filter old stored results at read time.
20
+ - Explain when no content-preset assessment was recorded and report aggregate assessment coverage in local telemetry.
21
+ - Show whether each CMS evaluation had complete, partial, unavailable or unknown body coverage in both findings interfaces. Older findings without coverage are treated conservatively; a complete body does not establish rendered-page or overall editorial quality.
22
+ - Preserve available prose while marking body coverage unverified when automatic selection encounters an unrecognized conventional body field. Hosts can still explicitly select the fields constituting the rendered body.
23
+ - Preserve ordered Portable Text when it is mixed with custom components. Unmapped components leave coverage unverified; explicitly mapped components can be included or deliberately excluded from editorial body evaluation.
24
+
9
25
  ## [0.9.0] - 2026-11-10
10
26
 
11
27
  ### Added
package/INSTALL.md CHANGED
@@ -23,6 +23,48 @@ aexeoPlugin({
23
23
  })
24
24
  ```
25
25
 
26
+ ## External gates in configured mode
27
+
28
+ The default descriptor loads no external code. Hosts that need custom gates can
29
+ provide a trusted runtime entrypoint exporting `createPlugin(options)` and call
30
+ Aexeo's configured entry with a runtime provider. Package this module under a
31
+ specifier your EmDash build can import, then set the descriptor's `entrypoint`
32
+ to that specifier. EmDash serializes descriptor options as JSON, so a callback
33
+ cannot be placed in `aexeoPlugin` options.
34
+
35
+ ```ts
36
+ // Example host-owned runtime module, published as @example/aexeo-runtime
37
+ import { createPlugin as createAexeo } from "@aeptus/aexeo-emdash/configured";
38
+ import type { ConfiguredPluginOptions, ExternalGateProvider } from "@aeptus/aexeo-emdash/configured";
39
+
40
+ const externalGates: ExternalGateProvider = async ({ input }) => [{
41
+ extension: "example.rule",
42
+ parameters: {},
43
+ input,
44
+ diagnostics: [], // Replace with your trusted checker and its diagnostics.
45
+ }];
46
+
47
+ export function createPlugin(options: ConfiguredPluginOptions) {
48
+ return createAexeo(options, { externalGates });
49
+ }
50
+ ```
51
+
52
+ In the host's configuration, use
53
+ `{ ...aexeoPlugin({ contentPreset: { name: "custom", sources: { custom: "..." } } }), entrypoint: "@example/aexeo-runtime" }`.
54
+ The callback runs on save and refresh only when the resolved preset has a custom
55
+ gate. It receives the selected document’s
56
+ projected input, selected preset and collection, and returns results bound to
57
+ the input and the gate's exact parameters. The preset must declare the matching
58
+ custom gate. Aexeo reports stale or missing results as incomplete. If the
59
+ provider fails, modern reports retain other findings and mark external gates as
60
+ not checked; older sidecar clients that cannot represent coverage still fail.
61
+ The input may include private content and
62
+ evidence. The host owns provider trust, timeouts, resource limits and any
63
+ network transfer. This runtime injection does not configure the sandbox worker.
64
+ An optional `onExternalGateTelemetry` runtime callback receives only provider
65
+ duration and success/error status, with no content or document identifiers.
66
+ It measures projection, provider call and result evaluation, not whether the returned gates passed.
67
+
26
68
  ## Content coverage
27
69
 
28
70
  Portable Text bodies provide text, headings, paragraphs and links to content
@@ -30,13 +72,24 @@ presets. A plain text body provides text only. EmDash custom blocks are
30
72
  project-specific; their flattened text is available to the legacy site audit,
31
73
  but content-preset gates that require body capabilities are reported as
32
74
  `not_checked` until a faithful mapping is provided. The configured plugin
33
- returns `content_preset_incomplete` for such a report, preserving its existing
34
- fail-closed behavior. This avoids treating unobserved headings, paragraphs or
35
- links as absent. An explicitly empty body
75
+ persists available findings alongside each gate status and its reason. The
76
+ sidecar also reports these assessments to updated clients; older clients retain
77
+ the fail-closed behavior for incomplete presets. This avoids treating unobserved
78
+ headings, paragraphs or links as absent. An explicitly empty body
36
79
  is distinct from an unavailable body. When an entry has several candidate
37
80
  content fields, the default first-field projection remains unverified because
38
81
  it cannot establish which fields appear in the rendered page.
39
82
 
83
+ During a CMS refresh, failed collection listings, invalid pagination and
84
+ incomplete bodies make sitewide and cross-document results unavailable. Aexeo
85
+ hides old cross-document findings and shows the coverage reason in the admin
86
+ views and `sitewideAssessment` in the findings API. `aexeo.sitewide_coverage`
87
+ logs only an aggregate status. A complete CMS listing is not proof that the
88
+ CMS inventory matches a rendered site or represents an atomic snapshot;
89
+ concurrent edits and refreshes are not isolated by the host's KV interface.
90
+ CMS-only evaluation does not assert that links are broken or pages are orphans;
91
+ use a rendered-site audit with matched inventory and coverage evidence.
92
+
40
93
  For custom blocks in configured mode, declare the ordered rendered content
41
94
  fields for each block type in the plugin configuration:
42
95
 
@@ -63,12 +116,69 @@ aexeoPlugin({
63
116
 
64
117
  `contentFieldsByCollection` declares the body fields rendered by each selected
65
118
  collection, in order. It is an explicit assertion of completeness, so include
66
- all rendered fields; entries without any selected field remain unavailable.
67
- In sandboxed mode, enter this object in `Content fields by collection (JSON)`.
119
+ all rendered fields. A selected field absent from the record makes the body
120
+ incomplete, while an explicitly present `null` is treated as empty. If no selected
121
+ field is present, the body remains unavailable. In sandboxed mode, enter this object in `Content fields by collection (JSON)`.
122
+ If this setting is malformed or cannot be read, save and Refresh keep recognized
123
+ prose but mark all body capabilities unavailable; check the plugin warning and
124
+ repair the setting. An unset setting uses automatic detection as usual.
125
+
126
+ Portable Text can also interleave text blocks and custom components. An
127
+ unknown component keeps its surrounding text but marks body capabilities
128
+ unverified. Best-effort text extracted from an unknown component is bounded to
129
+ 64 nesting levels, 50,000 visited values and 1,048,576 UTF-16 code units;
130
+ it may therefore be incomplete and must not be treated as a complete body. A host may map a component to `[]` only when it has verified that
131
+ the component contributes no content relevant to the evaluated body.
132
+
133
+ For an inline object inside a Portable Text block, use an explicit `inline`
134
+ mapping. It projects text and links in place without creating a new paragraph:
135
+
136
+ ```js
137
+ blockMappings: {
138
+ badge: { inline: [
139
+ { kind: "text", field: "label" },
140
+ { kind: "link", field: "linkLabel", hrefField: "href", optional: true },
141
+ ] },
142
+ }
143
+ ```
144
+
145
+ An empty `inline` array asserts the component adds no relevant body content.
146
+ An optional `capabilities` array limits the assertion just as for block mappings;
147
+ omitting it asserts all body capabilities. Only declare these mappings after
148
+ verifying the host renderer. Unknown components or invalid fields keep surrounding
149
+ spans but leave the body unverified. Mapped spans do not have original CMS source
150
+ locations because they are derived from component fields. Unchanged surrounding
151
+ spans can retain their original paths even when component projection changes their
152
+ position; ambiguous aliases and oversized or cyclic records remain unmapped.
153
+
154
+ The array form asserts that all four capabilities are complete. If a host can
155
+ only establish some capabilities, use the object form instead:
156
+
157
+ ```js
158
+ blockMappings: {
159
+ card: {
160
+ fields: [{ kind: "paragraph", field: "body" }],
161
+ capabilities: ["text", "paragraphs"],
162
+ },
163
+ }
164
+ ```
165
+
166
+ List a capability only when the projected fields faithfully represent **all**
167
+ of that component's rendered content relevant to it, including content outside
168
+ the listed fields. An empty `fields` array in the object form asserts only the
169
+ listed capabilities; for example, `fields: [], capabilities: ["headings"]`
170
+ asserts that the component contributes no headings, but says nothing about its
171
+ text, paragraphs or links. Aexeo intersects capabilities across every component,
172
+ selected field and nested rich-text block. Unknown, malformed or missing input
173
+ still removes the affected coverage conservatively. These assertions require
174
+ validation against the host renderer; they do not prove the content is correct.
68
175
 
69
176
  A block mapping is the site's assertion that those fields cover the rendered content,
70
- in order. `richText` accepts Portable Text arrays and preserves their headings
71
- and links; `heading` defaults to h2 and accepts levels 1 through 6. `repeat`
177
+ in order. `richText` accepts Portable Text arrays, including text mixed with
178
+ mapped custom components, or arrays of mapped custom components alone, and
179
+ preserves their headings and links. Unmapped or
180
+ malformed nested components and recursion beyond the mapping depth limit leave
181
+ body coverage unverified; `heading` defaults to h2 and accepts levels 1 through 6. `repeat`
72
182
  maps each item in an array;
73
183
  `optional: true` permits an absent field without inventing content. Every
74
184
  encountered block type must be
@@ -488,10 +598,73 @@ The export resolves public URLs through EmDash and paginates each selected
488
598
  collection. Entries without public URLs are reported as omitted, and entries
489
599
  with URLs default to `unknown` disposition. A host may supply `classify` when
490
600
  it has authoritative indexability and alias information. Repeated or missing
491
- cursors, failures, and page limits are reported. The inventory is always marked
601
+ cursors, failures, malformed collection responses or entries, and page limits are reported.
602
+ Malformed entries are omitted; a malformed collection page stops that collection
603
+ without discarding other collections. The inventory is always marked
492
604
  incomplete because pagination alone cannot establish a transactional snapshot or
493
605
  include routes outside the chosen collections. No HTTP endpoint is installed by
494
606
  this API. It cannot by itself establish that a crawl and CMS view describe the
495
607
  same publication, release and point in time.
496
608
 
609
+ Hosts whose rendered routes differ from EmDash's resolver can supply an async
610
+ `resolveUrl(collection, item)` returning the actual public URL or `null` when
611
+ no route is known. It replaces `getPublicUrl` for that export. The optional
612
+ `classify(item, url, collection)` callback can use collection-specific rules
613
+ and return `disposition`, `target`, and an explicit `locale` (including `null`
614
+ for unknown); omitting `locale` retains the CMS value. Callback failures leave
615
+ entries omitted or unclassified and are counted without exposing error details.
616
+ These host-supplied values are assertions, not proof of rendered routes,
617
+ publication state, snapshot identity, or inventory completeness.
618
+
619
+ URL resolution runs at most eight CMS requests concurrently by default. Set
620
+ `urlResolutionConcurrency` to an integer from 1 to 100 to suit the host's
621
+ capacity; use 1 for sequential requests. Pagination remains sequential.
622
+
497
623
  An optional `onTelemetry` callback receives only elapsed milliseconds and aggregate counts. It is disabled by default and does not receive URLs or content.
624
+
625
+ ### CMS coverage and rendered pages
626
+
627
+ The CMS integration evaluates content records, not the rendered page.
628
+ It does not report legacy SEO, social metadata, accessibility, page-size,
629
+ answer-block or citation-context findings as if generated HTML were observed.
630
+ The CMS dashboard score widget is unavailable for the same reason: CMS records
631
+ do not establish rendered-page coverage or a complete site inventory. Run Aexeo
632
+ against the built site to assess those checks. The `aexeo.page_coverage`
633
+ telemetry event marks rendered-page and generated-metadata coverage as not observed;
634
+ `aexeo.content_coverage` describes body projection separately.
635
+
636
+ The built-in `article` preset is a minimal non-empty text check, not a complete
637
+ editorial or SEO assessment. Choose and compose the editorial presets appropriate
638
+ to the content, or supply a project-specific preset.
639
+
640
+ When the host renderer selects a description from collection fields, configure
641
+ the same ordered fallback explicitly, for example:
642
+
643
+ ```ts
644
+ aexeoPlugin({
645
+ descriptionFieldsByCollection: { blog_posts: ["seo_description", "excerpt"] },
646
+ })
647
+ ```
648
+
649
+ In sandboxed mode, enter the equivalent JSON object, for example
650
+ `{"blog_posts":["seo_description","excerpt"]}`, in the plugin setting
651
+ `Description fields by collection (JSON)`. It applies to saves and Refresh.
652
+
653
+ The mapping projects source values; it does not prove what metadata the page
654
+ renderer generated. Explicit null or empty fields are observed as absent. A
655
+ missing, undefined or invalid field before the chosen fallback makes the source
656
+ unverified; an unused later field need not be present. Invalid settings remain
657
+ unverified. A `required_metadata` gate requesting `description` reports
658
+ `not_checked` when that source was not observed; other known-missing fields
659
+ can still produce findings. The `aexeo.description_coverage` log contains
660
+ aggregate counts of observed and unverified source projections without content
661
+ or identifiers.
662
+
663
+ Content preset gate outcomes, including `not_checked` and their reasons, are
664
+ stored with the current route findings and exposed in CMS views and the data
665
+ route. The preset panel lists passed, failed and unchecked gates, whether they
666
+ are blocking, and available measurements and thresholds. Older stored reports
667
+ may not contain measurements; missing measurements are not shown as zero. A
668
+ pass covers only the configured checks and is not an overall quality score. A failed evaluation clears findings for that revision and records an
669
+ error; it must not be interpreted as a clean assessment. `aexeo.preset_coverage`
670
+ logs aggregate counts without routes, gate identifiers, reasons or content.
package/README.md CHANGED
@@ -181,3 +181,11 @@ for the sandboxed setup runbook.
181
181
  ## License
182
182
 
183
183
  MIT — see [LICENSE](./LICENSE).
184
+
185
+ ### Host-supplied link observations
186
+
187
+ The optional content API can evaluate explicitly supplied link reachability
188
+ observations without network access in WASM. See [content gate documentation](https://github.com/schiste/Aexeo/blob/main/docs/content-gates.md#emdash-host-observations) for snapshot binding,
189
+ privacy and incomplete-coverage behavior. Configured save and refresh hooks invoke
190
+ a host observer only when it is explicitly installed and the selected preset requests
191
+ the gate. The host owns its network policy and request limits.
package/dist/adapter.d.ts CHANGED
@@ -20,7 +20,28 @@ export type CustomBlockField = {
20
20
  fields: readonly CustomBlockField[];
21
21
  optional?: boolean;
22
22
  };
23
- export type CustomBlockMappings = Record<string, readonly CustomBlockField[]>;
23
+ /** Capabilities that a host can establish for a component's rendered content. */
24
+ export type BodyCapability = "text" | "headings" | "paragraphs" | "links";
25
+ /** Ordered fields projected within the surrounding Portable Text block. */
26
+ export type InlineComponentField = {
27
+ kind: "text";
28
+ field: string;
29
+ optional?: boolean;
30
+ } | {
31
+ kind: "link";
32
+ field: string;
33
+ hrefField: string;
34
+ optional?: boolean;
35
+ };
36
+ /** The object form asserts coverage only for the listed capabilities. */
37
+ export type CustomBlockMapping = readonly CustomBlockField[] | {
38
+ fields: readonly CustomBlockField[];
39
+ capabilities: readonly BodyCapability[];
40
+ } | {
41
+ inline: readonly InlineComponentField[];
42
+ capabilities?: readonly BodyCapability[];
43
+ };
44
+ export type CustomBlockMappings = Record<string, CustomBlockMapping>;
24
45
  export interface EmdashContentItem {
25
46
  id: string;
26
47
  type: string;
@@ -45,6 +66,12 @@ export interface EmdashContentMeta {
45
66
  title: string;
46
67
  /** Exact URL returned by EmDash, or null when this entry has no public route. */
47
68
  publicUrl: string | null;
69
+ /** The content could not be adapted; route and title are from the previous snapshot. */
70
+ adaptationFailed?: true;
71
+ /** Original paths for unchanged Portable Text blocks in this exact snapshot. */
72
+ bodySourcePaths?: Array<Array<string | number> | null>;
73
+ /** Original text paths for unchanged spans within projected blocks. */
74
+ bodySourceSpanPaths?: Array<Array<Array<string | number> | null> | null>;
48
75
  /** The host's `updatedAt` for the row this entry was adapted from. */
49
76
  updatedAt?: string;
50
77
  }
@@ -70,18 +97,21 @@ export interface AdaptedContent {
70
97
  * accounts for collection URL patterns, locale prefixes, and slash policy;
71
98
  * slug-derived paths are not equivalent to the site's actual public URLs.
72
99
  */
73
- export declare function adaptContentItemWithContext(content: EmdashContentItem, contentApi: ContentUrlApi, defaultLocale?: string, blockMappings?: CustomBlockMappings, contentFields?: readonly string[]): Promise<AdaptedContent>;
100
+ export declare function adaptContentItemWithContext(content: EmdashContentItem, contentApi: ContentUrlApi, defaultLocale?: string, blockMappings?: CustomBlockMappings, contentFields?: readonly string[], descriptionFields?: readonly string[]): Promise<AdaptedContent>;
74
101
  /**
75
102
  * Synchronous adapter for callers that do not have a host content API.
76
103
  * It deliberately uses a stable identity route; callers should use
77
104
  * adaptContentItemWithContext whenever EmDash can resolve the public URL.
78
105
  */
79
106
  export declare function contentItemToEmdashDocument(content: EmdashContentItem, blockMappings?: CustomBlockMappings): EmdashDocument;
80
- export declare function adaptContentItem(content: EmdashContentItem, options?: {
107
+ type AdaptContentOptions = {
81
108
  route?: string;
82
109
  publicUrl?: string | null;
83
110
  defaultLocale?: string;
84
111
  blockMappings?: CustomBlockMappings | undefined;
85
112
  contentFields?: readonly string[];
86
- }): AdaptedContent;
113
+ descriptionFields?: readonly string[];
114
+ };
115
+ export declare function adaptContentItem(content: EmdashContentItem, options?: AdaptContentOptions): AdaptedContent;
116
+ export {};
87
117
  //# sourceMappingURL=adapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Findings.d.ts","sourceRoot":"","sources":["../../src/admin/Findings.tsx"],"names":[],"mappings":"AA2BA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAa/B,wBAAgB,QAAQ,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CA2L5C"}
1
+ {"version":3,"file":"Findings.d.ts","sourceRoot":"","sources":["../../src/admin/Findings.tsx"],"names":[],"mappings":"AA2BA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAe/B,wBAAgB,QAAQ,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAiN5C"}
package/dist/admin.js CHANGED
@@ -166,7 +166,7 @@ function PillarView({
166
166
  finding.layers?.secondaries?.length ? /* @__PURE__ */ jsx(SecondariesChips, { layers: finding.layers.secondaries }) : null
167
167
  ] }, i)) })
168
168
  ] }),
169
- findings.length === 0 ? sitewide.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-sm text-kumo-subtle", children: "All clean on this layer." }) : null : /* @__PURE__ */ jsx("div", { className: "overflow-x-auto rounded border border-kumo-line", children: /* @__PURE__ */ jsxs("table", { className: "w-full text-left text-sm", children: [
169
+ findings.length === 0 ? sitewide.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-sm text-kumo-subtle", children: "No findings from the available CMS checks on this layer." }) : null : /* @__PURE__ */ jsx("div", { className: "overflow-x-auto rounded border border-kumo-line", children: /* @__PURE__ */ jsxs("table", { className: "w-full text-left text-sm", children: [
170
170
  /* @__PURE__ */ jsx("thead", { className: "bg-kumo-tint", children: /* @__PURE__ */ jsxs("tr", { children: [
171
171
  /* @__PURE__ */ jsx("th", { className: "px-3 py-2 font-medium text-kumo-subtle", children: "Route" }),
172
172
  /* @__PURE__ */ jsx("th", { className: "px-3 py-2 font-medium text-kumo-subtle", children: "Rule" }),
@@ -800,6 +800,27 @@ function EntityLegitimacy() {
800
800
 
801
801
  // src/admin/Findings.tsx
802
802
  import { useCallback as useCallback4, useEffect as useEffect4, useState as useState4 } from "react";
803
+
804
+ // src/cms-coverage.ts
805
+ function cmsBodyCoverageNotice(coverage) {
806
+ if (coverage === "complete") return void 0;
807
+ return coverage === void 0 ? "Body coverage is unknown for this evaluation; save or refresh to reassess it." : `Body coverage is ${coverage}; content checks depending on missing capabilities cannot be evaluated reliably.`;
808
+ }
809
+
810
+ // src/assessment-display.ts
811
+ function describeGate(gate) {
812
+ const status = gate.status === "not_checked" ? "not checked" : gate.status;
813
+ const reason = gate.status === "not_checked" ? `: ${gate.reason ?? "required input unavailable"}` : "";
814
+ const metrics = Object.entries(gate.measurements ?? {}).map(([key, value]) => `${key.replaceAll("_", " ")}: ${value}`).join(", ");
815
+ return `${gate.gate_id} ${status}${reason} (${gate.blocking ? "blocking" : "advisory"})${metrics ? ` \u2014 ${metrics}` : ""}`;
816
+ }
817
+ function summarizeGates(gates) {
818
+ const counts = { passed: 0, failed: 0, not_checked: 0 };
819
+ for (const gate of gates) counts[gate.status]++;
820
+ return `${gates.length} configured checks: ${counts.passed} passed, ${counts.failed} failed, ${counts.not_checked} not checked`;
821
+ }
822
+
823
+ // src/admin/Findings.tsx
803
824
  import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
804
825
  var PLUGIN_ID4 = "aexeo-emdash";
805
826
  var API_BASE4 = "/_emdash/api";
@@ -888,6 +909,7 @@ function Findings() {
888
909
  if (payload === null) {
889
910
  return /* @__PURE__ */ jsx8("div", { className: "p-4 text-sm text-kumo-subtle", children: "No data." });
890
911
  }
912
+ const missingAssessments = payload.routes.filter((route) => route.assessment === void 0).length;
891
913
  const routesByPath = /* @__PURE__ */ new Map();
892
914
  for (const route of payload.routes) {
893
915
  routesByPath.set(route.route, route);
@@ -896,7 +918,7 @@ function Findings() {
896
918
  /* @__PURE__ */ jsxs5("header", { className: "flex items-center justify-between gap-4", children: [
897
919
  /* @__PURE__ */ jsxs5("div", { children: [
898
920
  /* @__PURE__ */ jsx8("h1", { className: "text-xl font-semibold", children: "SEO findings" }),
899
- /* @__PURE__ */ jsx8("p", { className: "mt-1 text-sm text-kumo-subtle", children: payload.totals.findings === 0 ? /* @__PURE__ */ jsx8(Fragment2, { children: "No findings yet \u2014 click Refresh to evaluate the site." }) : /* @__PURE__ */ jsxs5(Fragment2, { children: [
921
+ /* @__PURE__ */ jsx8("p", { className: "mt-1 text-sm text-kumo-subtle", children: payload.totals.findings === 0 ? /* @__PURE__ */ jsx8(Fragment2, { children: payload.totals.documentsIndexed === 0 ? "No CMS records indexed yet." : "No findings from the available CMS checks." }) : /* @__PURE__ */ jsxs5(Fragment2, { children: [
900
922
  payload.totals.findings,
901
923
  " findings across ",
902
924
  payload.totals.routes,
@@ -919,7 +941,19 @@ function Findings() {
919
941
  }
920
942
  )
921
943
  ] }),
944
+ /* @__PURE__ */ jsx8("p", { className: "text-sm text-kumo-subtle", children: "Rendered page markup, generated metadata and sitewide link inventory are not checked here. Audit the built site for page-level and link findings." }),
945
+ missingAssessments > 0 && /* @__PURE__ */ jsxs5("p", { className: "rounded border border-kumo-line p-3 text-sm", children: [
946
+ "No content preset assessment was recorded for ",
947
+ missingAssessments,
948
+ " document(s); absence of findings is not an editorial quality assessment."
949
+ ] }),
922
950
  toast !== null && /* @__PURE__ */ jsx8("div", { className: "rounded border border-kumo-line bg-kumo-tint p-3 text-sm", children: toast }),
951
+ payload.sitewideAssessment?.status === "error" && /* @__PURE__ */ jsxs5("p", { className: "rounded border border-kumo-line p-3 text-sm", children: [
952
+ "Sitewide checks unavailable: ",
953
+ payload.sitewideAssessment.reason,
954
+ ". ",
955
+ payload.sitewideAssessment.detail
956
+ ] }),
923
957
  payload.sitewideFindings.length > 0 && /* @__PURE__ */ jsxs5("section", { className: "rounded border border-kumo-line p-3", children: [
924
958
  /* @__PURE__ */ jsx8("h2", { className: "text-sm font-medium", children: "Sitewide" }),
925
959
  /* @__PURE__ */ jsx8("ul", { className: "mt-2 space-y-1 text-sm", children: payload.sitewideFindings.map((finding, i) => /* @__PURE__ */ jsxs5("li", { className: "flex items-start gap-2", children: [
@@ -928,7 +962,25 @@ function Findings() {
928
962
  /* @__PURE__ */ jsx8("span", { className: "flex-1", children: finding.message })
929
963
  ] }, i)) })
930
964
  ] }),
931
- payload.findings.length === 0 ? /* @__PURE__ */ jsx8("p", { className: "text-sm text-kumo-subtle", children: payload.totals.documentsIndexed === 0 ? "No documents indexed \u2014 click Refresh to do an initial sweep." : "All indexed documents are clean." }) : /* @__PURE__ */ jsx8("div", { className: "overflow-x-auto rounded border border-kumo-line", children: /* @__PURE__ */ jsxs5("table", { className: "w-full text-left text-sm", children: [
965
+ payload.routes.filter((route) => route.assessment !== void 0 || route.body_coverage !== "complete").map((route) => /* @__PURE__ */ jsxs5("section", { className: "rounded border border-kumo-line p-3 text-sm", children: [
966
+ /* @__PURE__ */ jsx8("strong", { children: route.route }),
967
+ route.assessment?.status !== "error" && cmsBodyCoverageNotice(route.body_coverage) && /* @__PURE__ */ jsx8("p", { children: cmsBodyCoverageNotice(route.body_coverage) }),
968
+ route.assessment?.status === "error" ? /* @__PURE__ */ jsxs5("p", { children: [
969
+ "Evaluation failed: ",
970
+ route.assessment.reason,
971
+ ". Findings are unavailable for this revision."
972
+ ] }) : route.assessment?.status === "evaluated" ? /* @__PURE__ */ jsxs5("details", { children: [
973
+ /* @__PURE__ */ jsxs5("summary", { children: [
974
+ "Content preset: ",
975
+ route.assessment.preset,
976
+ " \u2014 ",
977
+ summarizeGates(route.assessment.gates)
978
+ ] }),
979
+ /* @__PURE__ */ jsx8("p", { children: "Results cover only these configured checks." }),
980
+ /* @__PURE__ */ jsx8("ul", { children: route.assessment.gates.map((gate) => /* @__PURE__ */ jsx8("li", { children: describeGate(gate) }, gate.gate_id)) })
981
+ ] }) : null
982
+ ] }, route.route)),
983
+ payload.findings.length === 0 ? /* @__PURE__ */ jsx8("p", { className: "text-sm text-kumo-subtle", children: payload.totals.documentsIndexed === 0 ? "No documents indexed \u2014 click Refresh to do an initial sweep." : "No findings from the available CMS checks." }) : /* @__PURE__ */ jsx8("div", { className: "overflow-x-auto rounded border border-kumo-line", children: /* @__PURE__ */ jsxs5("table", { className: "w-full text-left text-sm", children: [
932
984
  /* @__PURE__ */ jsx8("thead", { className: "bg-kumo-tint", children: /* @__PURE__ */ jsxs5("tr", { children: [
933
985
  /* @__PURE__ */ jsx8("th", { className: "px-3 py-2 font-medium text-kumo-subtle", children: "Route" }),
934
986
  /* @__PURE__ */ jsx8("th", { className: "px-3 py-2 font-medium text-kumo-subtle", children: "Rule" }),
@@ -941,7 +993,22 @@ function Findings() {
941
993
  /* @__PURE__ */ jsx8("td", { className: "px-3 py-2 align-top", children: /* @__PURE__ */ jsx8(RouteLinks2, { finding, info: routeInfo }) }),
942
994
  /* @__PURE__ */ jsx8("td", { className: "px-3 py-2 align-top", children: /* @__PURE__ */ jsx8("code", { className: "rounded bg-kumo-tint px-1.5 py-0.5 font-mono text-xs", children: finding.rule_id }) }),
943
995
  /* @__PURE__ */ jsx8("td", { className: "px-3 py-2 align-top", children: /* @__PURE__ */ jsx8(SeverityBadge2, { severity: finding.severity }) }),
944
- /* @__PURE__ */ jsx8("td", { className: "px-3 py-2 align-top", children: finding.message })
996
+ /* @__PURE__ */ jsxs5("td", { className: "px-3 py-2 align-top", children: [
997
+ finding.message,
998
+ finding.aexeo_cms_location ? /* @__PURE__ */ jsxs5("div", { className: "text-xs text-kumo-subtle", children: [
999
+ "CMS path ",
1000
+ JSON.stringify(finding.aexeo_cms_location.path),
1001
+ ", UTF-16 offset ",
1002
+ finding.aexeo_cms_location.utf16_offset
1003
+ ] }) : finding.aexeo_source_location ? /* @__PURE__ */ jsxs5("div", { className: "text-xs text-kumo-subtle", children: [
1004
+ "Projected body: block ",
1005
+ finding.aexeo_source_location.block_index + 1,
1006
+ ", span ",
1007
+ finding.aexeo_source_location.span_index + 1,
1008
+ ", UTF-16 offset ",
1009
+ finding.aexeo_source_location.utf16_offset
1010
+ ] }) : finding.aexeo_origin === "content_preset" ? /* @__PURE__ */ jsx8("div", { className: "text-xs text-kumo-subtle", children: "Projected location unavailable" }) : null
1011
+ ] })
945
1012
  ] }, i);
946
1013
  }) })
947
1014
  ] }) })
@@ -0,0 +1,10 @@
1
+ import type { DocumentAssessment } from "./plugin.js";
2
+ type Gate = Extract<DocumentAssessment, {
3
+ status: "evaluated";
4
+ }>["gates"][number];
5
+ /** Plain text for both admin renderers; measurements may be absent on older records. */
6
+ export declare function describeGate(gate: Gate): string;
7
+ /** Counts describe only the gates that were configured, including unchecked gates. */
8
+ export declare function summarizeGates(gates: readonly Gate[]): string;
9
+ export {};
10
+ //# sourceMappingURL=assessment-display.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assessment-display.d.ts","sourceRoot":"","sources":["../src/assessment-display.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEtD,KAAK,IAAI,GAAG,OAAO,CAAC,kBAAkB,EAAE;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC;AAElF,wFAAwF;AACxF,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAK/C;AAED,sFAAsF;AACtF,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,GAAG,MAAM,CAI7D"}
@@ -0,0 +1,10 @@
1
+ import type { EmdashDocument, Finding } from "./types.js";
2
+ export declare function isCmsObservableFinding(finding: Finding, bodyComplete?: boolean): boolean;
3
+ export declare function isLegacyCmsObservableFinding(finding: Finding, bodyComplete?: boolean): boolean;
4
+ export declare function hasCompleteBody(document: EmdashDocument): boolean;
5
+ /** Coverage of the body supplied for one evaluation, not of the rendered page. */
6
+ export type CmsBodyCoverage = "complete" | "partial" | "unavailable";
7
+ export declare function cmsBodyCoverage(document: EmdashDocument): CmsBodyCoverage;
8
+ /** Short editor-facing explanation; absent coverage is a legacy or failed result. */
9
+ export declare function cmsBodyCoverageNotice(coverage: CmsBodyCoverage | undefined): string | undefined;
10
+ //# sourceMappingURL=cms-coverage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cms-coverage.d.ts","sourceRoot":"","sources":["../src/cms-coverage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAS1D,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,UAAO,GAAG,OAAO,CAErF;AAED,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,UAAO,GAAG,OAAO,CAK3F;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAIjE;AAED,kFAAkF;AAClF,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,SAAS,GAAG,aAAa,CAAC;AAErE,wBAAgB,eAAe,CAAC,QAAQ,EAAE,cAAc,GAAG,eAAe,CAGzE;AAED,qFAAqF;AACrF,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,eAAe,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAK/F"}
@@ -1,9 +1,11 @@
1
1
  import type { Suppression } from "./suppressions.js";
2
- import type { ContentPresetOptions } from "./content-evaluator.js";
2
+ import type { ContentPresetOptions, ExternalGateProvider, ExternalGateTelemetry, LinkObservationProvider, LinkProviderTelemetry } from "./content-evaluator.js";
3
+ export type { ExternalGateProvider, ExternalGateTelemetry, LinkObservationProvider, LinkProviderTelemetry } from "./content-evaluator.js";
3
4
  import type { CustomBlockMappings } from "./adapter.js";
4
5
  export interface ConfiguredPluginOptions {
5
6
  blockMappings?: CustomBlockMappings;
6
7
  contentFieldsByCollection?: Record<string, readonly string[]>;
8
+ descriptionFieldsByCollection?: Record<string, readonly string[]>;
7
9
  /** Optional portable preset evaluated in addition to the existing site checks. */
8
10
  contentPreset?: ContentPresetOptions;
9
11
  /**
@@ -29,6 +31,13 @@ export interface ConfiguredPluginOptions {
29
31
  */
30
32
  suppressions?: readonly Suppression[];
31
33
  }
32
- export declare function createPlugin(options?: ConfiguredPluginOptions): unknown;
34
+ /** Runtime-only dependencies must be installed by trusted host code, not JSON options. */
35
+ export interface ConfiguredPluginRuntime {
36
+ externalGates?: ExternalGateProvider;
37
+ onExternalGateTelemetry?: (event: ExternalGateTelemetry) => void;
38
+ linkObservations?: LinkObservationProvider;
39
+ onLinkProviderTelemetry?: (event: LinkProviderTelemetry) => void;
40
+ }
41
+ export declare function createPlugin(options?: ConfiguredPluginOptions, runtime?: ConfiguredPluginRuntime): unknown;
33
42
  export default createPlugin;
34
43
  //# sourceMappingURL=configured.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"configured.d.ts","sourceRoot":"","sources":["../src/configured.ts"],"names":[],"mappings":"AAwCA,OAAO,KAAK,EAAE,WAAW,EAAqB,MAAM,mBAAmB,CAAC;AAKxE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,KAAK,EAAE,mBAAmB,EAAqB,MAAM,cAAc,CAAC;AAuH3E,MAAM,WAAW,uBAAuB;IACtC,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,yBAAyB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC;IAC9D,kFAAkF;IAClF,aAAa,CAAC,EAAE,oBAAoB,CAAC;IACrC;;;OAGG;IACH,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEhC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEvC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEvC;;;;;OAKG;IACH,YAAY,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;CACvC;AAED,wBAAgB,YAAY,CAAC,OAAO,GAAE,uBAA4B,GAAG,OAAO,CAmJ3E;eAIc,YAAY"}
1
+ {"version":3,"file":"configured.d.ts","sourceRoot":"","sources":["../src/configured.ts"],"names":[],"mappings":"AAwCA,OAAO,KAAK,EAAE,WAAW,EAAqB,MAAM,mBAAmB,CAAC;AAKxE,OAAO,KAAK,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAChK,YAAY,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC1I,OAAO,KAAK,EAAE,mBAAmB,EAAqB,MAAM,cAAc,CAAC;AAuH3E,MAAM,WAAW,uBAAuB;IACtC,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,yBAAyB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC;IAC9D,6BAA6B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC;IAClE,kFAAkF;IAClF,aAAa,CAAC,EAAE,oBAAoB,CAAC;IACrC;;;OAGG;IACH,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEhC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEvC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEvC;;;;;OAKG;IACH,YAAY,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;CACvC;AAED,0FAA0F;AAC1F,MAAM,WAAW,uBAAuB;IACtC,aAAa,CAAC,EAAE,oBAAoB,CAAC;IACrC,uBAAuB,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACjE,gBAAgB,CAAC,EAAE,uBAAuB,CAAC;IAC3C,uBAAuB,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;CAClE;AAED,wBAAgB,YAAY,CAAC,OAAO,GAAE,uBAA4B,EAAE,OAAO,GAAE,uBAA4B,GAAG,OAAO,CAsJlH;eAIc,YAAY"}