@aeptus/aexeo-emdash 0.4.0 → 0.6.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.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,119 @@ and the project follows [Semantic Versioning](https://semver.org/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.6.0] - 2026-05-03
10
+
11
+ **Breaking change**: the `seogeo` → `aexeo` rename across the
12
+ codebase reaches the published API. Hosts on 0.5.x using the
13
+ sandboxed factory or the env-var fallback need to update their
14
+ imports and config. The configured factory was already named
15
+ `aexeoPlugin` in 0.5.x, so consumers using only that path are
16
+ unaffected.
17
+
18
+ **Compatibility:** verified against emdash `0.7.0` and `0.8.0`.
19
+
20
+ ### Changed (breaking)
21
+
22
+ - **Sandboxed factory rename:** `seogeoPluginSandboxed(...)` is now
23
+ `aexeoPluginSandboxed(...)`. Update your import:
24
+
25
+ ```ts
26
+ // before (0.5.x)
27
+ import { seogeoPluginSandboxed } from "@aeptus/aexeo-emdash";
28
+ // after (0.6.0)
29
+ import { aexeoPluginSandboxed } from "@aeptus/aexeo-emdash";
30
+ ```
31
+
32
+ - **Sandboxed options type rename:** `SeogeoSandboxedOptions` →
33
+ `AexeoSandboxedOptions`. Same migration as above for any host
34
+ that referenced the type name explicitly.
35
+
36
+ - **Env var rename:** `SEOGEO_EVALUATOR_HOST` →
37
+ `AEXEO_EVALUATOR_HOST`. Update any CI / Cloudflare Pages build
38
+ config that sets the old name. The fallback chain is unchanged
39
+ otherwise (factory option > env var > none).
40
+
41
+ - **Plugin id rename:** the plugin's emdash id is now `aexeo-emdash`
42
+ (was `aexeo-seogeo`). This affects:
43
+ - admin URL paths: `/admin/plugins/aexeo-emdash/...` (was
44
+ `/admin/plugins/aexeo-seogeo/...`)
45
+ - any host code that referenced the plugin id explicitly (e.g.
46
+ in `usePluginPage(pluginId, ...)` or in plugin-bridge URLs)
47
+ - the React `adminEntry` URL convention is unchanged at the
48
+ HTTP route level (the React pages still mount under the new
49
+ plugin id automatically)
50
+
51
+ - **Widget id rename:** `seogeo-score` → `aexeo-score`. Hosts that
52
+ declared this widget id explicitly in their dashboard config need
53
+ to update.
54
+
55
+ ### Notes for hosts upgrading from 0.5.x
56
+
57
+ The configured factory has been `aexeoPlugin` since 0.5.0 — sites
58
+ using only `aexeoPlugin({ ... })` need no code changes for this
59
+ release. The breaking changes above only affect:
60
+
61
+ 1. Hosts using the sandboxed factory.
62
+ 2. Hosts deploying with the `SEOGEO_EVALUATOR_HOST` env var.
63
+ 3. Host-side code or workflows that hardcode the plugin id
64
+ (`aexeo-seogeo`) or widget id (`seogeo-score`).
65
+
66
+ Migration is a sed-and-rebuild for most hosts. The rename was the
67
+ last user-facing trace of the original `seogeo` codebase name —
68
+ 0.6.0 closes the renaming pass that started across the workspace
69
+ in late April.
70
+
71
+ ## [0.5.0] - 2026-05-01
72
+
73
+ Three follow-ups from real-world adoption feedback after 0.4.0:
74
+
75
+ - richer suppression selectors so editors can target by collection
76
+ and document status, not just route + rule
77
+ - ergonomic collections API (`includeCollections` /
78
+ `excludeCollections`) for sites whose schema is close to the
79
+ default but needs minor tweaks
80
+ - README now leads with the suppressions glob semantics so consumers
81
+ migrating from local patches don't have to dig through the
82
+ CHANGELOG to learn that `*` is single-segment and `**` is recursive
83
+
84
+ **Compatibility:** verified against emdash `0.7.0` and `0.8.0`.
85
+
86
+ ### Added
87
+
88
+ - **`Suppression.collections`** — silence findings for documents in
89
+ the named emdash collections.
90
+ - **`Suppression.statuses`** — silence findings for documents in the
91
+ named statuses (`"draft"`, `"published"`, etc.). Useful for
92
+ preventing draft-stage findings from cluttering the dashboard.
93
+ - **`includeCollections`** factory option — adds slugs to the
94
+ default `["posts", "pages"]`. For sites that have the defaults
95
+ PLUS extras (e.g. blog adapter + `guides` and `faqs`).
96
+ - **`excludeCollections`** factory option — removes slugs from the
97
+ default. For sites that have most of the defaults but want to
98
+ skip one.
99
+
100
+ ### Changed
101
+
102
+ - **`SuppressionFilter.apply` signature** — now takes a
103
+ `SuppressionContext` object (`{ route, collection?, status? }`)
104
+ instead of a bare route string. Direct callers of `apply` will
105
+ see a TypeScript error and need a one-line update; the public
106
+ factory API (`aexeoPlugin({ suppressions })`) is unchanged.
107
+
108
+ ### Notes for hosts upgrading from 0.4.x
109
+
110
+ - No automatic behavior change. New selectors and options default
111
+ to undefined and are ignored unless the host opts in.
112
+ - Selector matching is **AND across selectors, OR across rules**.
113
+ A suppression with both `routePattern: "/fr-fr/**"` and
114
+ `collections: ["pages"]` only silences findings on French pages,
115
+ not on French blog posts.
116
+ - Sitewide findings (route `*`) ignore `collections` /
117
+ `statuses` selectors — those findings are inherently
118
+ cross-document and have no single collection or status to match.
119
+ Use `routePattern` (or omit it) and `ruleIds` for sitewide
120
+ suppressions.
121
+
9
122
  ## [0.4.0] - 2026-05-01
10
123
 
11
124
  Adds upstreamed support for editor-workflow finding suppressions.
@@ -16,13 +129,13 @@ patch over the published plugin.
16
129
 
17
130
  ### Added
18
131
 
19
- - **`seogeoPlugin({ suppressions })` option.** Each rule silences
132
+ - **`aexeoPlugin({ suppressions })` option.** Each rule silences
20
133
  findings matching the route pattern (glob) AND/OR a rule-id set.
21
134
  Applied before findings are persisted to KV — suppressed findings
22
135
  never reach the dashboard, /findings, or the per-document panel.
23
136
 
24
137
  ```ts
25
- seogeoPlugin({
138
+ aexeoPlugin({
26
139
  suppressions: [
27
140
  { routePattern: "/privacy", ruleIds: ["RULE001"] },
28
141
  { routePattern: "/fr-fr/**", ruleIds: ["RULE002"] },
@@ -50,7 +163,7 @@ patch over the published plugin.
50
163
  and the filter is a no-op until the host opts in.
51
164
  - Suppressions are plugin-only by design. The CLI `check` continues
52
165
  to surface every finding; if you want to silence findings at the
53
- CLI layer, use `seogeo.toml`'s `[ignore]` block. The two surfaces
166
+ CLI layer, use `aexeo.toml`'s `[ignore]` block. The two surfaces
54
167
  serve different audiences: the plugin is editorial workflow, the
55
168
  CLI is build-gating.
56
169
 
@@ -144,10 +257,10 @@ Block Kit (no link needs there).
144
257
  emdash's `usePluginPage` hook picks this up and renders the
145
258
  React component in place of the Block Kit fallback.
146
259
  - **Two new HTTP routes** the React component consumes:
147
- - `POST /_emdash/api/plugins/aexeo-seogeo/data` — read current
260
+ - `POST /_emdash/api/plugins/aexeo-emdash/data` — read current
148
261
  findings + per-route metadata + computed URLs (no
149
262
  re-evaluation).
150
- - `POST /_emdash/api/plugins/aexeo-seogeo/refresh` — sweep the
263
+ - `POST /_emdash/api/plugins/aexeo-emdash/refresh` — sweep the
151
264
  configured collections, write findings to KV, return the same
152
265
  payload as `/data` plus a refresh summary.
153
266
  Both routes return JSON in the shape exported as `FindingsPayload`
@@ -192,7 +305,7 @@ rule-engine change).
192
305
 
193
306
  ### Added
194
307
 
195
- - **`seogeoPlugin({ collections })` option** for configured mode.
308
+ - **`aexeoPlugin({ collections })` option** for configured mode.
196
309
  Lets sites with non-default collection slugs override which
197
310
  collections the Refresh button sweeps. Defaults to
198
311
  `["posts", "pages"]` when omitted (the slugs from
@@ -230,15 +343,15 @@ First public release.
230
343
 
231
344
  ### Added
232
345
 
233
- - `seogeoPlugin()` factory for **configured mode** — the recommended
346
+ - `aexeoPlugin()` factory for **configured mode** — the recommended
234
347
  install path for first-party emdash sites. Plugin runs in-process
235
348
  inside the host Worker. No sidecar deploy, no auth token, no admin
236
349
  Setup page.
237
- - `seogeoPluginSandboxed({ evaluatorHost })` factory for **sandboxed
350
+ - `aexeoPluginSandboxed({ evaluatorHost })` factory for **sandboxed
238
351
  mode** — preserved for future third-party-deploy scenarios where
239
352
  the plugin code shouldn't have full host access. Requires a
240
353
  separately-deployed sidecar Worker (template at
241
- `seogeo-crawl-worker` in the source repo).
354
+ `aexeo-crawl-worker` in the source repo).
242
355
  - Block Kit admin pages: findings table, per-document panel,
243
356
  intelligence-score dashboard widget. Refresh button on the
244
357
  findings page sweeps every document in the configured collections.
@@ -246,7 +359,7 @@ First public release.
246
359
  automatic re-evaluation of the changed document and update the
247
360
  findings table without manual intervention.
248
361
  - WASM-backed evaluator powered by the `aexeo-emdash-bridge` Rust
249
- crate (same engine as the seogeo CLI). Compiles via the consumer's
362
+ crate (same engine as the Aexeo CLI). Compiles via the consumer's
250
363
  Vite/Wrangler chain — `vite-plugin-wasm` is a peer-side runtime
251
364
  dependency for Vite-driven Cloudflare deploys.
252
365
 
@@ -266,7 +379,9 @@ First public release.
266
379
  `astro.config.mjs` for the WASM import to resolve to a
267
380
  precompiled `WebAssembly.Module`. Not optional.
268
381
 
269
- [Unreleased]: https://github.com/schiste/Aexeo/compare/aexeo-emdash-v0.4.0...HEAD
382
+ [Unreleased]: https://github.com/schiste/Aexeo/compare/aexeo-emdash-v0.6.0...HEAD
383
+ [0.6.0]: https://github.com/schiste/Aexeo/compare/aexeo-emdash-v0.5.0...aexeo-emdash-v0.6.0
384
+ [0.5.0]: https://github.com/schiste/Aexeo/compare/aexeo-emdash-v0.4.0...aexeo-emdash-v0.5.0
270
385
  [0.4.0]: https://github.com/schiste/Aexeo/compare/aexeo-emdash-v0.3.0...aexeo-emdash-v0.4.0
271
386
  [0.3.0]: https://github.com/schiste/Aexeo/compare/aexeo-emdash-v0.2.0...aexeo-emdash-v0.3.0
272
387
  [0.2.0]: https://github.com/schiste/Aexeo/compare/aexeo-emdash-v0.1.2...aexeo-emdash-v0.2.0
package/INSTALL.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Installing `@aeptus/aexeo-emdash`
2
2
 
3
- This package adds Aexeo's seogeo SEO/GEO content evaluator to an emdash
3
+ This package adds Aexeo SEO/GEO content evaluation to an emdash
4
4
  site. Findings show up as a Block Kit admin page; a sidebar widget
5
5
  shows the site's current intelligence score; saves auto-evaluate the
6
6
  changed document.
@@ -9,11 +9,11 @@ changed document.
9
9
 
10
10
  The package exports two factories:
11
11
 
12
- - **`seogeoPlugin()`** — **configured mode** (recommended). Plugin
12
+ - **`aexeoPlugin()`** — **configured mode** (recommended). Plugin
13
13
  runs in-process inside the host emdash Worker. No separate
14
14
  deployment, no auth token, no admin Setup page. Use this for
15
15
  first-party emdash sites.
16
- - **`seogeoPluginSandboxed({ evaluatorHost })`** — **sandboxed
16
+ - **`aexeoPluginSandboxed({ evaluatorHost })`** — **sandboxed
17
17
  mode**. Plugin runs inside emdash's Worker Loader isolate; WASM
18
18
  evaluation runs in a separate sidecar Worker the operator
19
19
  deploys. Use this only when a third party hosts emdash and
@@ -42,7 +42,7 @@ npm install @aeptus/aexeo-emdash vite-plugin-wasm
42
42
  `vite-plugin-wasm` is required because Vite's defaults treat `.wasm`
43
43
  imports as static-asset URLs, but Cloudflare Workers can only run
44
44
  WASM as precompiled `WebAssembly.Module` instances. The plugin
45
- bridges the two; without it, the seogeo plugin's first call throws
45
+ bridges the two; without it, the Aexeo plugin's first call throws
46
46
  "WASM module did not resolve to a WebAssembly.Module."
47
47
 
48
48
  > **If installing from a private git remote or as a vendored
@@ -54,7 +54,7 @@ bridges the two; without it, the seogeo plugin's first call throws
54
54
  ```js
55
55
  import cloudflare from "@astrojs/cloudflare";
56
56
  import { d1, r2 } from "@emdash-cms/cloudflare";
57
- import { seogeoPlugin } from "@aeptus/aexeo-emdash";
57
+ import { aexeoPlugin } from "@aeptus/aexeo-emdash";
58
58
  import { defineConfig } from "astro/config";
59
59
  import emdash from "emdash/astro";
60
60
  import wasm from "vite-plugin-wasm";
@@ -68,7 +68,7 @@ export default defineConfig({
68
68
  // workerd disallow runtime WebAssembly.instantiate from raw
69
69
  // bytes, so the bundler has to do the compilation.
70
70
  plugins: [wasm()],
71
- // The seogeo plugin's WASM import confuses Vite's dep
71
+ // The Aexeo plugin's WASM import confuses Vite's dep
72
72
  // optimizer when it tries to pre-bundle the package.
73
73
  optimizeDeps: { exclude: ["@aeptus/aexeo-emdash"] },
74
74
  },
@@ -76,7 +76,7 @@ export default defineConfig({
76
76
  emdash({
77
77
  database: d1({ binding: "DB" }),
78
78
  storage: r2({ binding: "MEDIA" }),
79
- plugins: [seogeoPlugin()],
79
+ plugins: [aexeoPlugin()],
80
80
  }),
81
81
  ],
82
82
  });
@@ -96,7 +96,7 @@ no sidecar to deploy.
96
96
  http://localhost:4321/_emdash/admin/plugins
97
97
  ```
98
98
 
99
- The seogeo plugin will appear in the list. Click it.
99
+ The Aexeo plugin will appear in the list. Click it.
100
100
 
101
101
  3. The findings page renders with a Refresh button. Click **Refresh**
102
102
  — toast says "Refreshed N routes (M findings across K documents)"
@@ -151,7 +151,7 @@ token to rotate, no Setup page to revisit.
151
151
 
152
152
  **Verify after a plugin update:**
153
153
 
154
- 1. Visit `/admin/plugins/aexeo-seogeo/findings` and click **Refresh**.
154
+ 1. Visit `/admin/plugins/aexeo-emdash/findings` and click **Refresh**.
155
155
  Toast should show non-zero rules sweeping. (A zero count *can*
156
156
  be valid for a clean site, but if you previously had findings
157
157
  and now have none, suspect the upgrade.)
@@ -216,7 +216,7 @@ Treat anything outside that range as best-effort.
216
216
 
217
217
  ## Removing
218
218
 
219
- Delete the dependency, the import, and the `seogeoPlugin()` line in
219
+ Delete the dependency, the import, and the `aexeoPlugin()` line in
220
220
  `integrations:[emdash({plugins:[...]})]`. The KV keys the plugin
221
221
  wrote remain in your KV namespace — purge with
222
222
  `wrangler kv:key delete --prefix=findings:` and
@@ -243,26 +243,26 @@ Trade-offs vs. configured mode:
243
243
  ```js
244
244
  // astro.config.mjs (sandboxed mode)
245
245
  import { sandbox } from "@emdash-cms/cloudflare";
246
- import { seogeoPluginSandboxed } from "@aeptus/aexeo-emdash";
246
+ import { aexeoPluginSandboxed } from "@aeptus/aexeo-emdash";
247
247
 
248
248
  emdash({
249
249
  database: d1({ binding: "DB" }),
250
250
  storage: r2({ binding: "MEDIA" }),
251
251
  sandboxed: [
252
- seogeoPluginSandboxed({
252
+ aexeoPluginSandboxed({
253
253
  // Public host of the deployed sidecar Worker.
254
- evaluatorHost: "seogeo-crawl-worker.<subdomain>.workers.dev",
254
+ evaluatorHost: "aexeo-crawl-worker.<subdomain>.workers.dev",
255
255
  }),
256
256
  ],
257
257
  sandboxRunner: sandbox(),
258
258
  });
259
259
  ```
260
260
 
261
- The sidecar Worker template lives at `packages/seogeo-crawl-worker/`
261
+ The sidecar Worker template lives at `packages/aexeo-crawl-worker/`
262
262
  in this repo. Per-site deploy:
263
263
 
264
264
  ```bash
265
- cd seogeo-crawl-worker
265
+ cd aexeo-crawl-worker
266
266
  # Edit wrangler.toml: name, R2 bucket name, SITE_URL
267
267
  npx wrangler login
268
268
  npx wrangler r2 bucket create <bucket-name>
@@ -271,7 +271,7 @@ echo "$(openssl rand -hex 32)" | npx wrangler secret put EVAL_TOKEN
271
271
  ```
272
272
 
273
273
  Then in the admin UI, visit
274
- `/admin/plugins/aexeo-seogeo/setup` and paste the deployed URL +
274
+ `/admin/plugins/aexeo-emdash/setup` and paste the deployed URL +
275
275
  the same token.
276
276
 
277
277
  ## Alternative install sources
@@ -316,7 +316,7 @@ present, double-check the package version is recent (≥ the version
316
316
  that switched to direct .wasm imports — see git log for `Switch
317
317
  configured-mode WASM from inlined bytes to direct .wasm import`).
318
318
 
319
- **`seogeo: WASM module did not resolve to a WebAssembly.Module`**
319
+ **`aexeo: WASM module did not resolve to a WebAssembly.Module`**
320
320
  The bundler resolved the .wasm import but produced something other
321
321
  than a Module (URL string, Uint8Array). Same fix as above: ensure
322
322
  `vite-plugin-wasm` is loaded.
@@ -327,7 +327,7 @@ sandboxed two-arg ctx shape. Update; it's fixed in the version with
327
327
  `Switch configured-mode WASM from inlined bytes to direct .wasm
328
328
  import` in the commit log.
329
329
 
330
- **`/admin/plugins` doesn't list seogeo, but `/findings` works.** The
330
+ **`/admin/plugins` doesn't list Aexeo, but `/findings` works.** The
331
331
  emdash version's plugins meta page may filter out plugins without a
332
332
  `/` adminPage entry. The package declares one explicitly; if you see
333
333
  this on a recent version, it's an emdash regression — file upstream.
@@ -344,7 +344,7 @@ Node adapter.
344
344
 
345
345
  ## What the plugin actually does
346
346
 
347
- - **Findings page** (`/_emdash/admin/plugins/aexeo-seogeo/findings`):
347
+ - **Findings page** (`/_emdash/admin/plugins/aexeo-emdash/findings`):
348
348
  Block Kit table of every rule violation across the site. Filter by
349
349
  severity. Click a route in the picker to drill into per-document
350
350
  findings.
@@ -371,6 +371,6 @@ inline. Findings are stored in the host's plugin KV (the
371
371
  `PluginContext.kv` accessor). The Refresh button does the same thing
372
372
  but for every document in every configured collection. The WASM
373
373
  itself is the same `aexeo-emdash-bridge` Rust crate that powers the
374
- seogeo CLI; it's compiled to WebAssembly via wasm-pack and imported
374
+ Aexeo CLI; it's compiled to WebAssembly via wasm-pack and imported
375
375
  by the host's bundler (Vite + `vite-plugin-wasm`). No separate
376
376
  service, no sidecar, no auth token.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 Aexeo
3
+ Copyright (c) 2026 Aeptus
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @aeptus/aexeo-emdash
2
2
 
3
- Aexeo's seogeo SEO/GEO content evaluator as an emdash plugin.
3
+ Aexeo SEO/GEO content evaluator as an emdash plugin.
4
4
 
5
5
  Adds a Findings admin page, per-document panel, and dashboard
6
6
  intelligence-score widget to an emdash site. Saves auto-evaluate the
@@ -14,7 +14,7 @@ npm install @aeptus/aexeo-emdash vite-plugin-wasm
14
14
 
15
15
  ```js
16
16
  // astro.config.mjs
17
- import { seogeoPlugin } from "@aeptus/aexeo-emdash";
17
+ import { aexeoPlugin } from "@aeptus/aexeo-emdash";
18
18
  import wasm from "vite-plugin-wasm";
19
19
 
20
20
  export default defineConfig({
@@ -26,7 +26,7 @@ export default defineConfig({
26
26
  emdash({
27
27
  database: d1({ binding: "DB" }),
28
28
  storage: r2({ binding: "MEDIA" }),
29
- plugins: [seogeoPlugin()],
29
+ plugins: [aexeoPlugin()],
30
30
  }),
31
31
  ],
32
32
  });
@@ -40,7 +40,7 @@ troubleshooting list, see [INSTALL.md](./INSTALL.md).
40
40
 
41
41
  ## What it does
42
42
 
43
- - **Findings page** at `/_emdash/admin/plugins/aexeo-seogeo/findings`:
43
+ - **Findings page** at `/_emdash/admin/plugins/aexeo-emdash/findings`:
44
44
  rule violations across the site, filterable by severity.
45
45
  - **Document panel** at `/document`: findings scoped to one document.
46
46
  - **Dashboard widget**: top-line intelligence score (citation, truth,
@@ -59,13 +59,108 @@ troubleshooting list, see [INSTALL.md](./INSTALL.md).
59
59
  bundler handles compilation at build time. `vite-plugin-wasm` is a
60
60
  hard requirement on the consumer side.
61
61
 
62
+ ## Configuring collections
63
+
64
+ The plugin sweeps `["posts", "pages"]` by default — the slugs the
65
+ `@emdash-cms/template-blog-cloudflare` template ships with. Three knobs
66
+ to override, in precedence order:
67
+
68
+ ```js
69
+ // Full override — replace the default entirely.
70
+ // Use when your schema has none of the default slugs.
71
+ aexeoPlugin({ collections: ["blog_posts", "pages"] })
72
+
73
+ // Extend the default — add slugs alongside posts + pages.
74
+ aexeoPlugin({ includeCollections: ["guides", "faqs"] })
75
+
76
+ // Subtract from the default — remove a slug.
77
+ aexeoPlugin({ excludeCollections: ["posts"] })
78
+
79
+ // Combine include + exclude (subtract first, then add).
80
+ // `collections` ignores both — it's the explicit-list override.
81
+ aexeoPlugin({
82
+ excludeCollections: ["posts"],
83
+ includeCollections: ["blog_posts", "guides"],
84
+ })
85
+ ```
86
+
87
+ Pointing any of these at a slug that doesn't exist is non-fatal:
88
+ the bridge's `content.list` returns empty and the missing collection
89
+ shows up in the Refresh summary's `errors` field.
90
+
91
+ ## Suppressing findings
92
+
93
+ When a finding is intentional (legal pages with non-standard SEO,
94
+ localized routes where a rule doesn't apply, draft documents whose
95
+ findings shouldn't surface yet), silence it with a suppression rule.
96
+ Suppressions are applied **before** findings are persisted to KV —
97
+ suppressed findings never reach the dashboard, `/findings`, or the
98
+ per-document panel.
99
+
100
+ ```js
101
+ aexeoPlugin({
102
+ suppressions: [
103
+ // route + rule
104
+ { routePattern: "/privacy", ruleIds: ["RULE001"] },
105
+
106
+ // recursive route subtree
107
+ { routePattern: "/fr-fr/**", ruleIds: ["RULE002"] },
108
+
109
+ // applies to every route
110
+ { ruleIds: ["RULE999"] },
111
+
112
+ // by collection
113
+ { collections: ["drafts"], ruleIds: ["RULE042"] },
114
+
115
+ // by document status
116
+ { statuses: ["draft"] }, // silence ALL findings on drafts
117
+ ],
118
+ })
119
+ ```
120
+
121
+ ### Glob syntax for `routePattern`
122
+
123
+ | Pattern | Matches |
124
+ |---|---|
125
+ | `*` | any chars **except** `/` |
126
+ | `**` | any chars **including** `/` (recursive) |
127
+ | `?` | exactly one char except `/` |
128
+
129
+ Patterns are anchored. `/about` matches only `/about`, not
130
+ `/about/team` — use `/about/**` if you want a subtree.
131
+
132
+ > **Migrating from a local patch**: if your previous setup used
133
+ > looser patterns (e.g. one-asterisk-means-everything), update them
134
+ > on bump. `*` is intentionally single-segment so editors can scope
135
+ > rules to a level of the path hierarchy without recursive surprises.
136
+
137
+ ### Selector semantics
138
+
139
+ A rule may set any combination of `routePattern`, `ruleIds`,
140
+ `collections`, and `statuses`. Matching is **AND across selectors,
141
+ OR across rules**: a finding is suppressed when at least one rule
142
+ matches it; a rule matches when every selector it sets matches the
143
+ finding's context.
144
+
145
+ Empty rules (`{}` with no selectors) are rejected at plugin
146
+ construction. That's a kill-switch for all findings everywhere
147
+ and almost certainly an editor mistake.
148
+
149
+ `collections` and `statuses` only meaningful for per-document
150
+ findings. Sitewide findings (cross-document audit issues) are
151
+ matched only by `routePattern` and `ruleIds`.
152
+
153
+ Suppressions are plugin-only by design. The CLI's `check` is the
154
+ canonical strict audit; if you want to silence findings at the CLI
155
+ layer, use `aexeo.toml`'s `[ignore]` block instead.
156
+
62
157
  ## Two factories
63
158
 
64
159
  The package exports two factories for different trust contexts:
65
160
 
66
- - `seogeoPlugin()` — **configured mode** (recommended). In-process
161
+ - `aexeoPlugin()` — **configured mode** (recommended). In-process
67
162
  plugin. Use for first-party emdash sites.
68
- - `seogeoPluginSandboxed({ evaluatorHost })` — **sandboxed mode**.
163
+ - `aexeoPluginSandboxed({ evaluatorHost })` — **sandboxed mode**.
69
164
  Requires a separately-deployed sidecar Worker. Use only when
70
165
  shipping to third-party emdash sites that shouldn't trust the
71
166
  plugin code with full host access.
package/dist/admin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // src/admin/Facts.tsx
2
2
  import { useCallback, useEffect, useState } from "react";
3
3
  import { jsx, jsxs } from "react/jsx-runtime";
4
- var PLUGIN_ID = "aexeo-seogeo";
4
+ var PLUGIN_ID = "aexeo-emdash";
5
5
  var API_BASE = "/_emdash/api";
6
6
  function Facts() {
7
7
  const [data, setData] = useState(null);
@@ -275,7 +275,7 @@ async function callRoute(kind, extra) {
275
275
  // src/admin/Findings.tsx
276
276
  import { useCallback as useCallback2, useEffect as useEffect2, useState as useState2 } from "react";
277
277
  import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
278
- var PLUGIN_ID2 = "aexeo-seogeo";
278
+ var PLUGIN_ID2 = "aexeo-emdash";
279
279
  var API_BASE2 = "/_emdash/api";
280
280
  function Findings() {
281
281
  const [state, setState] = useState2({
@@ -1,12 +1,20 @@
1
1
  import type { Suppression } from "./suppressions.js";
2
2
  export interface ConfiguredPluginOptions {
3
3
  /**
4
- * emdash collections the Refresh button sweeps. Comes through from
5
- * the descriptor's `options` field — see `seogeoPlugin({ collections })`
6
- * in src/index.ts. When undefined, falls back to DEFAULT_COLLECTIONS
7
- * (`["posts", "pages"]`).
4
+ * Full override of the swept collections. See `aexeoPlugin` in
5
+ * src/index.ts for the full precedence story.
8
6
  */
9
7
  collections?: readonly string[];
8
+ /**
9
+ * Add to the default `["posts", "pages"]`. Ignored when
10
+ * `collections` is set.
11
+ */
12
+ includeCollections?: readonly string[];
13
+ /**
14
+ * Remove from the default `["posts", "pages"]`. Applied before
15
+ * `includeCollections`. Ignored when `collections` is set.
16
+ */
17
+ excludeCollections?: readonly string[];
10
18
  /**
11
19
  * Editor-workflow suppressions. See `Suppression` in suppressions.ts
12
20
  * for the rule shape and matching semantics. Compiled once at plugin
@@ -1 +1 @@
1
- {"version":3,"file":"configured.d.ts","sourceRoot":"","sources":["../src/configured.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAoDrD,MAAM,WAAW,uBAAuB;IACtC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEhC;;;;;OAKG;IACH,YAAY,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;CACvC;AAED,wBAAgB,YAAY,CAAC,OAAO,GAAE,uBAA4B,GAAG,OAAO,CA+F3E;AAID,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"configured.d.ts","sourceRoot":"","sources":["../src/configured.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAmFrD,MAAM,WAAW,uBAAuB;IACtC;;;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,CAyG3E;AAID,eAAe,YAAY,CAAC"}
@@ -89,7 +89,14 @@ async function handleAfterSaveConfigured(event, ctx, evaluator, suppressionFilte
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
+ const filtered = suppressionFilter === void 0 ? pageFindings : suppressionFilter.apply(
93
+ {
94
+ route: document.route,
95
+ collection: adapted.meta.collection,
96
+ status: adapted.meta.status
97
+ },
98
+ pageFindings
99
+ );
93
100
  await kv.set(findingsKey(document.route), {
94
101
  route: document.route,
95
102
  findings: filtered
@@ -140,7 +147,7 @@ async function evaluateAndPersistAll(ctx, options) {
140
147
  }
141
148
  const result = await options.evaluator(documents);
142
149
  if (!result.ok) {
143
- log?.error?.(`seogeo evaluator failure (${result.reason})`, {
150
+ log?.error?.(`aexeo evaluator failure (${result.reason})`, {
144
151
  detail: result.detail
145
152
  });
146
153
  summary.errors.push(`${result.reason}: ${result.detail}`);
@@ -158,7 +165,13 @@ async function evaluateAndPersistAll(ctx, options) {
158
165
  }
159
166
  let totalAfterSuppression = 0;
160
167
  for (const [route, findings] of findingsByRoute) {
161
- const filtered = suppressionFilter === void 0 ? findings : suppressionFilter.apply(route, findings);
168
+ const stored = adaptedByRoute.get(route);
169
+ const context = {
170
+ route,
171
+ ...stored?.meta.collection === void 0 ? {} : { collection: stored.meta.collection },
172
+ ...stored?.meta.status === void 0 ? {} : { status: stored.meta.status }
173
+ };
174
+ const filtered = suppressionFilter === void 0 ? findings : suppressionFilter.apply(context, findings);
162
175
  await kv.set(findingsKey(route), { route, findings: filtered });
163
176
  summary.routesUpdated += 1;
164
177
  totalAfterSuppression += filtered.length;
@@ -418,7 +431,7 @@ function ensureInitialized() {
418
431
  }
419
432
  if (!(bridgeModule instanceof WebAssembly.Module)) {
420
433
  throw new Error(
421
- "seogeo: WASM module did not resolve to a WebAssembly.Module \u2014 the consumer's bundler isn't configured for .wasm imports. Add the .wasm loader to your Vite/wrangler config; see @aeptus/aexeo-emdash INSTALL.md for the recipe."
434
+ "aexeo: WASM module did not resolve to a WebAssembly.Module \u2014 the consumer's bundler isn't configured for .wasm imports. Add the .wasm loader to your Vite/wrangler config; see @aeptus/aexeo-emdash INSTALL.md for the recipe."
422
435
  );
423
436
  }
424
437
  const instance = new WebAssembly.Instance(bridgeModule, {
@@ -732,7 +745,7 @@ async function handleSave(ctx, body) {
732
745
 
733
746
  // src/suppressions.ts
734
747
  var NOOP_FILTER = {
735
- apply: (_route, findings) => [...findings]
748
+ apply: (_context, findings) => [...findings]
736
749
  };
737
750
  function compileSuppressions(rules) {
738
751
  if (rules === void 0 || rules.length === 0) {
@@ -741,25 +754,41 @@ function compileSuppressions(rules) {
741
754
  rules.forEach((rule, index) => {
742
755
  const hasRoute = rule.routePattern !== void 0 && rule.routePattern.length > 0;
743
756
  const hasRuleIds = rule.ruleIds !== void 0 && rule.ruleIds.length > 0;
744
- if (!hasRoute && !hasRuleIds) {
757
+ const hasCollections = rule.collections !== void 0 && rule.collections.length > 0;
758
+ const hasStatuses = rule.statuses !== void 0 && rule.statuses.length > 0;
759
+ if (!hasRoute && !hasRuleIds && !hasCollections && !hasStatuses) {
745
760
  throw new Error(
746
- `seogeoPlugin: suppressions[${index}] is empty \u2014 set routePattern, ruleIds, or both`
761
+ `aexeoPlugin: suppressions[${index}] is empty \u2014 set at least one of routePattern, ruleIds, collections, statuses`
747
762
  );
748
763
  }
749
764
  });
750
765
  const compiled = rules.map((rule) => ({
751
766
  matchRoute: rule.routePattern === void 0 ? matchAlways : globToMatcher(rule.routePattern),
752
- ruleIds: rule.ruleIds === void 0 || rule.ruleIds.length === 0 ? null : new Set(rule.ruleIds)
767
+ ruleIds: rule.ruleIds === void 0 || rule.ruleIds.length === 0 ? null : new Set(rule.ruleIds),
768
+ collections: rule.collections === void 0 || rule.collections.length === 0 ? null : new Set(rule.collections),
769
+ statuses: rule.statuses === void 0 || rule.statuses.length === 0 ? null : new Set(rule.statuses)
753
770
  }));
754
771
  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
- }));
772
+ apply(context, findings) {
773
+ return findings.filter(
774
+ (finding) => !compiled.some((rule) => {
775
+ if (!rule.matchRoute(context.route)) return false;
776
+ if (rule.ruleIds !== null && !rule.ruleIds.has(finding.rule_id)) {
777
+ return false;
778
+ }
779
+ if (rule.collections !== null) {
780
+ if (context.collection === void 0 || !rule.collections.has(context.collection)) {
781
+ return false;
782
+ }
783
+ }
784
+ if (rule.statuses !== null) {
785
+ if (context.status === void 0 || !rule.statuses.has(context.status)) {
786
+ return false;
787
+ }
788
+ }
789
+ return true;
790
+ })
791
+ );
763
792
  }
764
793
  };
765
794
  }
@@ -767,16 +796,35 @@ var matchAlways = () => true;
767
796
  function globToMatcher(pattern) {
768
797
  const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&");
769
798
  const DOUBLE_STAR_TOKEN = "";
770
- let body = escaped.replace(/\*\*/g, DOUBLE_STAR_TOKEN).replace(/\*/g, "[^/]*").replace(new RegExp(DOUBLE_STAR_TOKEN, "g"), ".*").replace(/\?/g, "[^/]");
799
+ const body = escaped.replace(/\*\*/g, DOUBLE_STAR_TOKEN).replace(/\*/g, "[^/]*").replace(new RegExp(DOUBLE_STAR_TOKEN, "g"), ".*").replace(/\?/g, "[^/]");
771
800
  const re = new RegExp(`^${body}$`);
772
801
  return (route) => re.test(route);
773
802
  }
774
803
 
775
804
  // src/version.ts
776
- var PACKAGE_VERSION = "0.4.0";
805
+ var PACKAGE_VERSION = "0.6.0";
777
806
 
778
807
  // src/configured.ts
779
808
  import { definePlugin } from "emdash";
809
+ function resolveCollections(explicit, include, exclude) {
810
+ if (explicit !== void 0) {
811
+ return [...explicit];
812
+ }
813
+ const excludeSet = new Set(exclude ?? []);
814
+ const base = DEFAULT_COLLECTIONS.filter(
815
+ (slug) => !excludeSet.has(slug)
816
+ );
817
+ if (include === void 0 || include.length === 0) {
818
+ return base;
819
+ }
820
+ const result = [...base];
821
+ for (const slug of include) {
822
+ if (!result.includes(slug)) {
823
+ result.push(slug);
824
+ }
825
+ }
826
+ return result;
827
+ }
780
828
  var inProcessEvaluator = async (documents) => {
781
829
  try {
782
830
  const raw = await evaluateDocuments2(JSON.stringify(documents));
@@ -795,10 +843,14 @@ var inProcessEvaluator = async (documents) => {
795
843
  }
796
844
  };
797
845
  function createPlugin(options = {}) {
798
- const collections = options.collections === void 0 ? DEFAULT_COLLECTIONS : [...options.collections];
846
+ const collections = resolveCollections(
847
+ options.collections,
848
+ options.includeCollections,
849
+ options.excludeCollections
850
+ );
799
851
  const suppressionFilter = compileSuppressions(options.suppressions);
800
852
  return definePlugin({
801
- id: "aexeo-seogeo",
853
+ id: "aexeo-emdash",
802
854
  version: PACKAGE_VERSION,
803
855
  capabilities: ["read:content"],
804
856
  hooks: {
@@ -820,8 +872,8 @@ function createPlugin(options = {}) {
820
872
  handler: (ctx) => handleAdminRoute(ctx, collections)
821
873
  },
822
874
  // JSON data endpoint for the React adminEntry. Two routes:
823
- // POST /_emdash/api/plugins/aexeo-seogeo/data — read current findings
824
- // POST /_emdash/api/plugins/aexeo-seogeo/refresh — sweep + read
875
+ // POST /_emdash/api/plugins/aexeo-emdash/data — read current findings
876
+ // POST /_emdash/api/plugins/aexeo-emdash/refresh — sweep + read
825
877
  // Returning JSON (not Block Kit blocks) lets the React
826
878
  // <Findings/> component render proper <a href> links to the
827
879
  // emdash edit page and the public site, which Block Kit can't
@@ -862,7 +914,7 @@ function createPlugin(options = {}) {
862
914
  { path: "/facts", label: "Truth manifest" }
863
915
  ],
864
916
  widgets: [
865
- { id: "seogeo-score", size: "third", title: "SEO score" }
917
+ { id: "aexeo-score", size: "third", title: "SEO score" }
866
918
  ]
867
919
  }
868
920
  });
@@ -901,7 +953,7 @@ async function handlePageLoad(ctx, page) {
901
953
  if (normalized === "" || normalized === "findings") {
902
954
  return renderFindingsPage(ctx);
903
955
  }
904
- if (normalized === "widget:seogeo-score") {
956
+ if (normalized === "widget:aexeo-score") {
905
957
  return renderScoreWidget(ctx);
906
958
  }
907
959
  if (normalized === "document") {
@@ -1049,7 +1101,7 @@ async function renderScoreWidget(ctx) {
1049
1101
  { type: "header", text: "SEO score" },
1050
1102
  {
1051
1103
  type: "context",
1052
- text: "No documents indexed \u2014 click Refresh on the seogeo findings page."
1104
+ text: "No documents indexed \u2014 click Refresh on the Aexeo findings page."
1053
1105
  }
1054
1106
  ]
1055
1107
  };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { seogeoPluginSandboxed } from "./sandbox.js";
2
- export type { PluginAdminPage, PluginAdminWidget, SandboxedPluginDescriptor, SeogeoSandboxedOptions, } from "./sandbox.js";
1
+ export { aexeoPluginSandboxed } from "./sandbox.js";
2
+ export type { PluginAdminPage, PluginAdminWidget, SandboxedPluginDescriptor, AexeoSandboxedOptions, } from "./sandbox.js";
3
3
  export interface ConfiguredPluginDescriptor {
4
4
  id: string;
5
5
  version: string;
@@ -18,7 +18,7 @@ export interface ConfiguredPluginDescriptor {
18
18
  title?: string;
19
19
  }[];
20
20
  }
21
- export interface SeogeoPluginOptions {
21
+ export interface AexeoPluginOptions {
22
22
  /**
23
23
  * emdash collections the plugin sweeps when an admin clicks
24
24
  * Refresh on the findings page. Order doesn't matter; the sweep
@@ -29,24 +29,57 @@ export interface SeogeoPluginOptions {
29
29
  *
30
30
  * Defaults to `["posts", "pages"]` (the slugs the
31
31
  * `@emdash-cms/template-blog-cloudflare` template ships with).
32
- * Override when your schema uses different collection slugs:
32
+ * Three knobs, in precedence order:
33
33
  *
34
- * seogeoPlugin({ collections: ["posts", "guides", "products"] })
34
+ * - `collections` — full override. When set, replaces the
35
+ * default entirely. Use this when your schema has none of the
36
+ * default slugs (e.g. a site with `blog_posts` and `pages`).
35
37
  *
36
- * Pointing this at a slug that doesn't exist in your schema is
37
- * non-fatal: the bridge's `content.list` returns empty and the
38
- * sweep records the missing collection in the Refresh summary's
39
- * `errors` field. Safe to ship a superset for a project that may
40
- * add collections later.
38
+ * aexeoPlugin({ collections: ["blog_posts", "pages"] })
39
+ *
40
+ * - `includeCollections` — extend the default. Adds slugs to
41
+ * the existing default. Use this when your schema has the
42
+ * default slugs PLUS extras.
43
+ *
44
+ * aexeoPlugin({ includeCollections: ["guides", "faqs"] })
45
+ *
46
+ * - `excludeCollections` — subtract from the default. Removes
47
+ * slugs from the existing default. Use this when your schema
48
+ * has the defaults but you want to skip one.
49
+ *
50
+ * aexeoPlugin({ excludeCollections: ["posts"] })
51
+ *
52
+ * `includeCollections` and `excludeCollections` may be combined
53
+ * (subtract first, then add). `collections` ignores both — it's
54
+ * the explicit-list override.
55
+ *
56
+ * Pointing any of these at a slug that doesn't exist in your
57
+ * schema is non-fatal: the bridge's `content.list` returns empty
58
+ * and the sweep records the missing collection in the Refresh
59
+ * summary's `errors` field. Safe to ship a superset for a project
60
+ * that may add collections later.
41
61
  */
42
62
  collections?: readonly string[];
63
+ /**
64
+ * Slugs to add on top of the default `["posts", "pages"]`. Ignored
65
+ * when `collections` is set (which fully overrides the default).
66
+ * See `collections` for the full precedence story.
67
+ */
68
+ includeCollections?: readonly string[];
69
+ /**
70
+ * Slugs to remove from the default `["posts", "pages"]`. Applied
71
+ * before `includeCollections`, so adding a slug back via include
72
+ * is a no-op (it was never removed). Ignored when `collections`
73
+ * is set.
74
+ */
75
+ excludeCollections?: readonly string[];
43
76
  /**
44
77
  * Editor-workflow suppressions. Each rule silences findings that
45
78
  * match the route pattern (glob) AND/OR are in the rule-id set.
46
79
  * Applied before findings are persisted to KV — suppressed findings
47
80
  * never reach the dashboard, /findings, or the per-document panel.
48
81
  *
49
- * seogeoPlugin({
82
+ * aexeoPlugin({
50
83
  * suppressions: [
51
84
  * { routePattern: "/privacy", ruleIds: ["RULE001"] },
52
85
  * { routePattern: "/fr-fr/**", ruleIds: ["RULE002"] },
@@ -63,7 +96,7 @@ export interface SeogeoPluginOptions {
63
96
  *
64
97
  * Suppressions are plugin-only by design. The CLI's `check` is the
65
98
  * canonical strict audit; if you want to silence findings at the
66
- * CLI layer, use `seogeo.toml`'s `[ignore]` block instead. The two
99
+ * CLI layer, use `aexeo.toml`'s `[ignore]` block instead. The two
67
100
  * surfaces serve different audiences: the plugin is editorial
68
101
  * workflow, the CLI is build-gating.
69
102
  */
@@ -71,5 +104,5 @@ export interface SeogeoPluginOptions {
71
104
  }
72
105
  export type { Suppression } from "./suppressions.js";
73
106
  import type { Suppression } from "./suppressions.js";
74
- export declare function seogeoPlugin(options?: SeogeoPluginOptions): ConfiguredPluginDescriptor;
107
+ export declare function aexeoPlugin(options?: AexeoPluginOptions): ConfiguredPluginDescriptor;
75
108
  //# sourceMappingURL=index.d.ts.map
@@ -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;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;IAEhC;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACH,YAAY,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;CACvC;AAED,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,wBAAgB,YAAY,CAC1B,OAAO,GAAE,mBAAwB,GAChC,0BAA0B,CAkD5B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,yBAAyB,EACzB,qBAAqB,GACtB,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,kBAAkB;IACjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCG;IACH,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEhC;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEvC;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEvC;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACH,YAAY,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;CACvC;AAED,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,wBAAgB,WAAW,CACzB,OAAO,GAAE,kBAAuB,GAC/B,0BAA0B,CAqE5B"}
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ var baseCapabilities = [
6
6
  "write:artifacts:public/llms-full.txt",
7
7
  "write:artifacts:public/facts.json",
8
8
  "write:artifacts:public/*.md.txt",
9
- "kv:seogeo-baselines"
9
+ "kv:aexeo-baselines"
10
10
  ];
11
11
  function buildCapabilities(evaluatorHost) {
12
12
  if (evaluatorHost === null) {
@@ -23,13 +23,13 @@ function buildAllowedHosts(evaluatorHost) {
23
23
  }
24
24
 
25
25
  // src/version.ts
26
- var PACKAGE_VERSION = "0.4.0";
26
+ var PACKAGE_VERSION = "0.6.0";
27
27
 
28
28
  // src/sandbox.ts
29
- function seogeoPluginSandboxed(options = {}) {
30
- const evaluatorHost = options.evaluatorHost ?? process.env.SEOGEO_EVALUATOR_HOST ?? null;
29
+ function aexeoPluginSandboxed(options = {}) {
30
+ const evaluatorHost = options.evaluatorHost ?? process.env.AEXEO_EVALUATOR_HOST ?? null;
31
31
  return {
32
- id: "aexeo-seogeo",
32
+ id: "aexeo-emdash",
33
33
  version: PACKAGE_VERSION,
34
34
  // Subpath export of this same package; must match package.json
35
35
  // `exports["./sandbox"]`.
@@ -37,7 +37,7 @@ function seogeoPluginSandboxed(options = {}) {
37
37
  format: "standard",
38
38
  capabilities: buildCapabilities(evaluatorHost),
39
39
  allowedHosts: buildAllowedHosts(evaluatorHost),
40
- // Pages mount at /admin/plugins/aexeo-seogeo/<path>. The page name
40
+ // Pages mount at /admin/plugins/aexeo-emdash/<path>. The page name
41
41
  // (without leading slash) is what the sandbox entry receives in
42
42
  // `body.page` when emdash POSTs the page_load interaction.
43
43
  adminPages: [
@@ -46,15 +46,15 @@ function seogeoPluginSandboxed(options = {}) {
46
46
  { path: "/setup", label: "Setup" }
47
47
  ],
48
48
  adminWidgets: [
49
- { id: "seogeo-score", size: "third", title: "SEO score" }
49
+ { id: "aexeo-score", size: "third", title: "SEO score" }
50
50
  ]
51
51
  };
52
52
  }
53
53
 
54
54
  // src/index.ts
55
- function seogeoPlugin(options = {}) {
55
+ function aexeoPlugin(options = {}) {
56
56
  return {
57
- id: "aexeo-seogeo",
57
+ id: "aexeo-emdash",
58
58
  version: PACKAGE_VERSION,
59
59
  // Subpath import resolved by the consumer's bundler at build
60
60
  // time — must match the package.json `exports["./configured"]`
@@ -76,12 +76,21 @@ function seogeoPlugin(options = {}) {
76
76
  // the structured-clone semantics of that codegen.
77
77
  options: {
78
78
  ...options.collections === void 0 ? {} : { collections: [...options.collections] },
79
- ...options.suppressions === void 0 ? {} : { suppressions: options.suppressions.map((rule) => ({ ...rule })) }
79
+ ...options.includeCollections === void 0 ? {} : { includeCollections: [...options.includeCollections] },
80
+ ...options.excludeCollections === void 0 ? {} : { excludeCollections: [...options.excludeCollections] },
81
+ ...options.suppressions === void 0 ? {} : {
82
+ suppressions: options.suppressions.map((rule) => ({
83
+ ...rule,
84
+ ...rule.ruleIds === void 0 ? {} : { ruleIds: [...rule.ruleIds] },
85
+ ...rule.collections === void 0 ? {} : { collections: [...rule.collections] },
86
+ ...rule.statuses === void 0 ? {} : { statuses: [...rule.statuses] }
87
+ }))
88
+ }
80
89
  },
81
90
  capabilities: [
82
91
  "read:content",
83
92
  "read:schema",
84
- "kv:seogeo-baselines"
93
+ "kv:aexeo-baselines"
85
94
  ],
86
95
  // adminPages drives the admin sidebar — one nav entry per item.
87
96
  // Don't list "/" alongside "/findings": both would render as
@@ -95,11 +104,11 @@ function seogeoPlugin(options = {}) {
95
104
  { path: "/document", label: "Document SEO" }
96
105
  ],
97
106
  adminWidgets: [
98
- { id: "seogeo-score", size: "third", title: "SEO score" }
107
+ { id: "aexeo-score", size: "third", title: "SEO score" }
99
108
  ]
100
109
  };
101
110
  }
102
111
  export {
103
- seogeoPlugin,
104
- seogeoPluginSandboxed
112
+ aexeoPlugin,
113
+ aexeoPluginSandboxed
105
114
  };
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
@@ -131,7 +131,7 @@ async function evaluateAndPersistAll(ctx, options) {
131
131
  }
132
132
  const result = await options.evaluator(documents);
133
133
  if (!result.ok) {
134
- log?.error?.(`seogeo evaluator failure (${result.reason})`, {
134
+ log?.error?.(`aexeo evaluator failure (${result.reason})`, {
135
135
  detail: result.detail
136
136
  });
137
137
  summary.errors.push(`${result.reason}: ${result.detail}`);
@@ -149,7 +149,13 @@ async function evaluateAndPersistAll(ctx, options) {
149
149
  }
150
150
  let totalAfterSuppression = 0;
151
151
  for (const [route, findings] of findingsByRoute2) {
152
- const filtered = suppressionFilter === void 0 ? findings : suppressionFilter.apply(route, findings);
152
+ const stored = adaptedByRoute.get(route);
153
+ const context = {
154
+ route,
155
+ ...stored?.meta.collection === void 0 ? {} : { collection: stored.meta.collection },
156
+ ...stored?.meta.status === void 0 ? {} : { status: stored.meta.status }
157
+ };
158
+ const filtered = suppressionFilter === void 0 ? findings : suppressionFilter.apply(context, findings);
153
159
  await kv.set(findingsKey(route), { route, findings: filtered });
154
160
  summary.routesUpdated += 1;
155
161
  totalAfterSuppression += filtered.length;
@@ -364,8 +370,8 @@ function failure(reason, rejected) {
364
370
 
365
371
  // src/mcp.ts
366
372
  var checkTool = {
367
- name: "seogeo.check",
368
- description: "Evaluate a list of EmdashDocument values against the seogeo rule engine and return the stable Finding contract. Mirrors the CLI's `seogeo-cli check` surface so agents, the admin UI, and the CI gate all see the same rule ids.",
373
+ name: "aexeo.check",
374
+ description: "Evaluate a list of EmdashDocument values against the Aexeo rule engine and return the stable Finding contract. Mirrors the CLI's `aexeo-cli check` surface so agents, the admin UI, and the CI gate all see the same rule ids.",
369
375
  inputSchema: {
370
376
  type: "object",
371
377
  properties: {
@@ -375,7 +381,7 @@ var checkTool = {
375
381
  },
376
382
  configJson: {
377
383
  type: "string",
378
- description: "Optional JSON-serialized seogeo Config. When absent the evaluator uses Config::default(), matching a cold CLI run."
384
+ description: "Optional JSON-serialized Aexeo config. When absent the evaluator uses Config::default(), matching a cold CLI run."
379
385
  }
380
386
  },
381
387
  required: ["documents"]
@@ -402,8 +408,8 @@ var checkTool = {
402
408
  }
403
409
  };
404
410
  var indexNowSubmitTool = {
405
- name: "seogeo.indexnow.submit",
406
- description: "Submit a list of URLs to the IndexNow freshness endpoint. Mirrors the seogeo-cli `indexnow submit` contract: the IndexNow protocol requires every submitted URL to belong to the configured site host. URLs that do not match the host are returned in `rejected` and never sent over the wire.",
411
+ name: "aexeo.indexnow.submit",
412
+ description: "Submit a list of URLs to the IndexNow freshness endpoint. Mirrors the aexeo-cli `indexnow submit` contract: the IndexNow protocol requires every submitted URL to belong to the configured site host. URLs that do not match the host are returned in `rejected` and never sent over the wire.",
407
413
  inputSchema: {
408
414
  type: "object",
409
415
  properties: {
@@ -435,7 +441,7 @@ function definePlugin(plugin) {
435
441
  }
436
442
  async function handleAdminRoute(input, ctx) {
437
443
  ctx.log?.info?.(
438
- `seogeo route: type=${input.input?.type} page=${input.input?.page ?? ""}`
444
+ `aexeo route: type=${input.input?.type} page=${input.input?.page ?? ""}`
439
445
  );
440
446
  const dispatch = { body: input.input, kv: ctx.kv, ctx };
441
447
  if (dispatch.body.type === "page_load") {
@@ -474,7 +480,7 @@ async function handlePageLoad(ctx, page) {
474
480
  if (normalized === "findings") {
475
481
  return renderFindingsPage(ctx);
476
482
  }
477
- if (normalized === "widget:seogeo-score") {
483
+ if (normalized === "widget:aexeo-score") {
478
484
  return renderScoreWidget(ctx);
479
485
  }
480
486
  if (normalized === "document") {
@@ -504,7 +510,7 @@ async function handleRefresh(ctx) {
504
510
  return {
505
511
  ok: false,
506
512
  reason: "config_missing",
507
- detail: "sidecar not configured \u2014 open the seogeo Setup page and enter your evaluator URL and token"
513
+ detail: "sidecar not configured \u2014 open the Aexeo Setup page and enter your evaluator URL and token"
508
514
  };
509
515
  }
510
516
  return evaluateViaSidecar(
@@ -763,10 +769,10 @@ function documentFindingsTable(findings) {
763
769
  async function renderSetupPage(ctx, options = {}) {
764
770
  const existing = await readSidecarConfig(ctx.kv);
765
771
  const blocks = [
766
- { type: "header", text: "seogeo setup" },
772
+ { type: "header", text: "Aexeo setup" },
767
773
  {
768
774
  type: "context",
769
- text: "Paste the URL and auth token of your deployed seogeo-crawl-worker. These are stored in plugin KV and read at runtime \u2014 no rebuild required after a change. Rotate the token here whenever you redeploy the sidecar with a new secret."
775
+ text: "Paste the URL and auth token of your deployed aexeo-crawl-worker. These are stored in plugin KV and read at runtime \u2014 no rebuild required after a change. Rotate the token here whenever you redeploy the sidecar with a new secret."
770
776
  }
771
777
  ];
772
778
  if (options.bannerError !== void 0) {
@@ -790,7 +796,7 @@ async function renderSetupPage(ctx, options = {}) {
790
796
  type: "text_input",
791
797
  action_id: "evaluator_url",
792
798
  label: "Sidecar URL",
793
- placeholder: "https://seogeo-crawl-worker.<subdomain>.workers.dev",
799
+ placeholder: "https://aexeo-crawl-worker.<subdomain>.workers.dev",
794
800
  initial_value: options.initialUrl ?? existing?.url ?? ""
795
801
  },
796
802
  {
package/dist/sandbox.d.ts CHANGED
@@ -18,8 +18,8 @@ export interface SandboxedPluginDescriptor {
18
18
  adminWidgets?: readonly PluginAdminWidget[];
19
19
  allowedHosts?: readonly string[];
20
20
  }
21
- export interface SeogeoSandboxedOptions {
21
+ export interface AexeoSandboxedOptions {
22
22
  evaluatorHost?: string;
23
23
  }
24
- export declare function seogeoPluginSandboxed(options?: SeogeoSandboxedOptions): SandboxedPluginDescriptor;
24
+ export declare function aexeoPluginSandboxed(options?: AexeoSandboxedOptions): SandboxedPluginDescriptor;
25
25
  //# sourceMappingURL=sandbox.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"AA0BA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,yBAAyB;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IAGnB,MAAM,EAAE,UAAU,CAAC;IACnB,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,UAAU,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IAGxC,YAAY,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC5C,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAeD,MAAM,WAAW,sBAAsB;IAgBrC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,qBAAqB,CACnC,OAAO,GAAE,sBAA2B,GACnC,yBAAyB,CAwB3B"}
1
+ {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"AA0BA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,yBAAyB;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IAGnB,MAAM,EAAE,UAAU,CAAC;IACnB,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,UAAU,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IAGxC,YAAY,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC5C,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAeD,MAAM,WAAW,qBAAqB;IAgBpC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,qBAA0B,GAClC,yBAAyB,CAwB3B"}
@@ -2,9 +2,16 @@ import type { Finding } from "./types.js";
2
2
  export interface Suppression {
3
3
  routePattern?: string;
4
4
  ruleIds?: readonly string[];
5
+ collections?: readonly string[];
6
+ statuses?: readonly string[];
7
+ }
8
+ export interface SuppressionContext {
9
+ route: string;
10
+ collection?: string;
11
+ status?: string;
5
12
  }
6
13
  export interface SuppressionFilter {
7
- apply(route: string, findings: readonly Finding[]): Finding[];
14
+ apply(context: SuppressionContext, findings: readonly Finding[]): Finding[];
8
15
  }
9
16
  export declare function compileSuppressions(rules: readonly Suppression[] | undefined): SuppressionFilter;
10
17
  //# sourceMappingURL=suppressions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"suppressions.d.ts","sourceRoot":"","sources":["../src/suppressions.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAkB1C,MAAM,WAAW,WAAW;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B;AAID,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC;CAC/D;AASD,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,SAAS,WAAW,EAAE,GAAG,SAAS,GACxC,iBAAiB,CAoCnB"}
1
+ {"version":3,"file":"suppressions.d.ts","sourceRoot":"","sources":["../src/suppressions.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAsB1C,MAAM,WAAW,WAAW;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B;AAOD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAID,MAAM,WAAW,iBAAiB;IAChC,KAAK,CACH,OAAO,EAAE,kBAAkB,EAC3B,QAAQ,EAAE,SAAS,OAAO,EAAE,GAC3B,OAAO,EAAE,CAAC;CACd;AASD,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,SAAS,WAAW,EAAE,GAAG,SAAS,GACxC,iBAAiB,CAyEnB"}
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const PACKAGE_VERSION = "0.4.0";
1
+ export declare const PACKAGE_VERSION = "0.6.0";
2
2
  //# sourceMappingURL=version.d.ts.map
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@aeptus/aexeo-emdash",
3
- "version": "0.4.0",
4
- "description": "Aexeo seogeo SEO/GEO content evaluator as an emdash plugin",
3
+ "version": "0.6.0",
4
+ "description": "Aexeo SEO/GEO content evaluator as an emdash plugin",
5
5
  "license": "MIT",
6
- "author": "Aexeo",
6
+ "author": "Aeptus",
7
7
  "homepage": "https://github.com/schiste/Aexeo/tree/main/packages/aexeo-emdash",
8
8
  "repository": {
9
9
  "type": "git",
Binary file