# SEO Domain Ontology

Status: Stage 5 architecture slice
Date: 2026-07-02
Package: `catalog/domain-packages/seo`

## Purpose

SEO Domain Ontology defines the reusable platform vocabulary for NDC SEO mod.
It must not replace per-project evidence and must not execute SEO mutations.

The package exists so the SEO module can participate in NodeDC-wide assistant routing
without hardcoding NODE.DC-specific product clusters into the generic SEO engine.

## Ownership Boundaries

Ontology Core owns:

- canonical SEO entity/action names;
- aliases;
- relations;
- guardrails;
- assistant action cards;
- resolver rules and binding types.

NDC SEO mod owns:

- project source import and live crawl;
- scan versions;
- project ontology extraction;
- semantic analysis;
- Wordstat/SERP/Webmaster/Metrica evidence collection;
- keyword decisions;
- optimization plans;
- rewrite variants;
- final validation;
- changeset/apply/export execution.

OPS Gateway and app-owned adapters own:

- permission enforcement;
- scopes/grants;
- confirmation;
- idempotency;
- audit.

## Three-Layer Model

`CoreOntologySnapshot`:

- stable platform meanings from Ontology Core;
- HUB, OPS Product, OPS Gateway, ENGINE, Assistant, and Future Interface Layer concepts;
- SEO package-level concepts after validation.

`SeoDomainOntology`:

- reusable `seo.*` entity/action/guardrail catalog;
- not tied to one site;
- ships with Ontology Core as a domain package.

`ProjectOntologyInstance`:

- versioned project/site evidence;
- extracted from source/crawl/content and user approvals;
- contains brand, offers, audiences, pages, sections, tone, constraints, entities, intents, and evidence refs;
- can propose ontology deltas but cannot silently mutate Ontology Core.

## Current SEO Entities

The first package slice defines:

- `seo.project`
- `seo.site`
- `seo.source`
- `seo.scan_version`
- `seo.scope_contract`
- `seo.scope_item`
- `seo.page`
- `seo.section`
- `seo.media_asset`
- `seo.project_ontology`
- `seo.semantic_profile`
- `seo.intent_cluster`
- `seo.demand_universe`
- `seo.semantic_anchor`
- `seo.anchor_review`
- `seo.wordstat_queue`
- `seo.seed_query`
- `seo.keyword`
- `seo.market_signal`
- `seo.keyword_curation_board`
- `seo.keyword_role_decision`
- `seo.keyword_map`
- `seo.landing_section_mapping`
- `seo.future_landing_gap`
- `seo.optimization_plan`
- `seo.rewrite_eligibility`
- `seo.semantic_block`
- `seo.rewrite_variant`
- `seo.validation_result`
- `seo.change_set`
- `seo.apply_result`
- `seo.expansion_opportunity`

`seo.expansion_opportunity` is deliberately marked `future-concept`.
It exists only to reserve the boundary for a later optional business/coverage branch.

## Assistant Actions

SEO assistant actions are registered as declarative future app-owned actions:

- `seo.project.read_context`
- `seo.project.scan`
- `seo.ontology.extract`
- `seo.semantic.analyze`
- `seo.anchor_review.approve`
- `seo.market.collect_wordstat`
- `seo.keyword.curate`
- `seo.keyword.map`
- `seo.mapping.approve`
- `seo.plan.build`
- `seo.rewrite.propose`
- `seo.validation.run`
- `seo.change_set.preview`
- `seo.change_set.apply`

All actions route to `adapter.seo.module_api` and currently use `adapterStatus: future`.
This is intentional: Ontology Core can resolve and classify intent before the SEO adapter exists,
but it must not pretend that live execution is ready.

## Guardrails

Hard rules:

- per-project SEO ontology is evidence, not global truth;
- keywords, Wordstat rows, SERP rows, and forecasts stay project evidence;
- semantic analysis, keyword map, rewrite, validation, and changeset must be bounded by scope contract;
- Wordstat/SERP collection must use only human-approved anchors from `seo.anchor_review`, never raw site text or automatic model proposals;
- strategy and optimization plan must consume curated keyword role decisions, not raw provider rows;
- future landing gaps are non-blocking strategy context and must not force materialization, rewrite, or random existing page selection;
- rewrite variants require approved existing page/section/content-field bindings and may be grouped by persisted semantic blocks;
- apply requires changeset, validation, dry-run/backup boundary, confirmation, and app-owned adapter;
- Ontology Core does not execute SEO source mutations.

## Stage 5 Keyword Curation

The model must pre-sort keyword candidates before strategy. The board has exactly five lanes:

- unresolved / `Неразобранные`;
- landing core / `Посадочное ядро`;
- supporting core / `Поддерживающее ядро`;
- differentiators / `Уточняющие / УТП`;
- long tail / `Длинный хвост`.

The user can move cards between lanes. Final strategy input includes only landing core,
supporting core, differentiators, and long tail. Unresolved keywords do not participate in
strategy, mapping, rewrite, or materialization.

Optional future rule:

- expansion opportunities are a separate future branch after core SEO results and market evidence.

## Current Runtime Gap

The SEO module has moved NODE.DC-specific clusters behind an explicit project ontology seed fixture.
Generic extraction must not inject NODE.DC aliases, `/modules/ops`, or AI-platform fixture phrases.
This is covered by:

```text
/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_SEO/seo_mode/seo_mode/server/src/scripts/checkOntologyUniversality.ts
```

The remaining gap is execution routing: Ontology Core declares SEO actions and guardrails, but the live
`adapter.seo.module_api` is still marked `future`. Assistant/MCP execution must follow the SEO-owned API
contract before it can simulate the full route:

```text
semantic profile -> demand universe -> anchor review -> Wordstat queue -> market signal -> keyword curation -> landing/section mapping -> strategy/rewrite eligibility
```

## Package Loading

Ontology Core now loads domain packages from:

```text
catalog/domain-packages/*
```

Each package may contribute:

- `entities.json`
- `relations.json`
- `aliases.json`
- `guardrails.json`
- `evidence.json`
- `resolver-rules.json`
- `context-bindings.json`
- `assistant-access-policy.json`
- `assistant-actions.json`
- `assistant-risk-policy.json`

The loader merges package catalogs into the base catalog before validation.
