feat(ai-workspace): support SEO codex provider bridge

This commit is contained in:
Codex
2026-07-03 08:43:37 +03:00
parent 1aceabee44
commit a7c6c34c82
26 changed files with 1649 additions and 36 deletions
@@ -0,0 +1,58 @@
{
"version": "0.1.0",
"updatedAt": "2026-07-02",
"aliases": [
{ "alias": "SEO mod", "canonicalId": "seo.project" },
{ "alias": "NDC SEO mod", "canonicalId": "seo.project" },
{ "alias": "seo project", "canonicalId": "seo.project" },
{ "alias": "site", "canonicalId": "seo.site" },
{ "alias": "сайт", "canonicalId": "seo.site" },
{ "alias": "source", "canonicalId": "seo.source" },
{ "alias": "scan", "canonicalId": "seo.scan_version" },
{ "alias": "scope", "canonicalId": "seo.scope_contract" },
{ "alias": "scope contract", "canonicalId": "seo.scope_contract" },
{ "alias": "page", "canonicalId": "seo.page" },
{ "alias": "страница", "canonicalId": "seo.page" },
{ "alias": "section", "canonicalId": "seo.section" },
{ "alias": "block", "canonicalId": "seo.section" },
{ "alias": "секция", "canonicalId": "seo.section" },
{ "alias": "блок", "canonicalId": "seo.section" },
{ "alias": "ProjectOntology", "canonicalId": "seo.project_ontology" },
{ "alias": "project ontology", "canonicalId": "seo.project_ontology" },
{ "alias": "semantic profile", "canonicalId": "seo.semantic_profile" },
{ "alias": "intent cluster", "canonicalId": "seo.intent_cluster" },
{ "alias": "demand universe", "canonicalId": "seo.demand_universe" },
{ "alias": "semantic anchor", "canonicalId": "seo.semantic_anchor" },
{ "alias": "смысловой якорь", "canonicalId": "seo.semantic_anchor" },
{ "alias": "anchor review", "canonicalId": "seo.anchor_review" },
{ "alias": "фиксация ключей", "canonicalId": "seo.anchor_review" },
{ "alias": "wordstat queue", "canonicalId": "seo.wordstat_queue" },
{ "alias": "очередь Wordstat", "canonicalId": "seo.wordstat_queue" },
{ "alias": "seed", "canonicalId": "seo.seed_query" },
{ "alias": "seed query", "canonicalId": "seo.seed_query" },
{ "alias": "keyword", "canonicalId": "seo.keyword" },
{ "alias": "ключ", "canonicalId": "seo.keyword" },
{ "alias": "ключевик", "canonicalId": "seo.keyword" },
{ "alias": "Wordstat signal", "canonicalId": "seo.market_signal" },
{ "alias": "market evidence", "canonicalId": "seo.market_signal" },
{ "alias": "keyword curation board", "canonicalId": "seo.keyword_curation_board" },
{ "alias": "карта распределения ключей", "canonicalId": "seo.keyword_curation_board" },
{ "alias": "keyword role", "canonicalId": "seo.keyword_role_decision" },
{ "alias": "роль ключа", "canonicalId": "seo.keyword_role_decision" },
{ "alias": "keyword map", "canonicalId": "seo.keyword_map" },
{ "alias": "landing section mapping", "canonicalId": "seo.landing_section_mapping" },
{ "alias": "маппинг посадочных", "canonicalId": "seo.landing_section_mapping" },
{ "alias": "future landing gap", "canonicalId": "seo.future_landing_gap" },
{ "alias": "будущая посадочная", "canonicalId": "seo.future_landing_gap" },
{ "alias": "optimization plan", "canonicalId": "seo.optimization_plan" },
{ "alias": "rewrite eligibility", "canonicalId": "seo.rewrite_eligibility" },
{ "alias": "semantic block", "canonicalId": "seo.semantic_block" },
{ "alias": "семантический блок", "canonicalId": "seo.semantic_block" },
{ "alias": "rewrite variant", "canonicalId": "seo.rewrite_variant" },
{ "alias": "validation result", "canonicalId": "seo.validation_result" },
{ "alias": "change set", "canonicalId": "seo.change_set" },
{ "alias": "changeset", "canonicalId": "seo.change_set" },
{ "alias": "apply result", "canonicalId": "seo.apply_result" },
{ "alias": "coverage expansion", "canonicalId": "seo.expansion_opportunity" }
]
}
@@ -0,0 +1,62 @@
{
"version": "0.1.0",
"updatedAt": "2026-07-02",
"capabilities": [
{ "id": "assistant.seo_read", "entityId": "assistant.capability", "level": "member", "summary": "Assistant can read SEO project context visible to the actor." },
{ "id": "assistant.seo_run_analysis", "entityId": "assistant.capability", "level": "member", "summary": "Assistant can request non-destructive SEO scan, ontology extraction, semantic analysis, and evidence collection in an authorized project." },
{ "id": "assistant.seo_plan_changes", "entityId": "assistant.capability", "level": "member", "summary": "Assistant can request anchor review, keyword curation, keyword map, optimization plan, rewrite variants, and validation previews." },
{ "id": "assistant.seo_apply_changes", "entityId": "assistant.capability", "level": "member", "summary": "Assistant can request an SEO changeset apply only through the SEO-owned adapter, confirmation, validation, and Gateway/app scopes." }
],
"roleMatrix": [
{
"roleId": "assistant_member",
"allowedCapabilities": [
"assistant.seo_read",
"assistant.seo_run_analysis",
"assistant.seo_plan_changes",
"assistant.seo_apply_changes"
],
"summary": "SEO actions are app-owned and remain bounded by SEO project permissions and Gateway scopes."
},
{
"roleId": "assistant_admin",
"allowedCapabilities": [
"assistant.seo_read",
"assistant.seo_run_analysis",
"assistant.seo_plan_changes",
"assistant.seo_apply_changes"
],
"summary": "Assistant admin does not bypass SEO project permissions; it only has the same SEO capabilities plus existing admin capabilities."
}
],
"operations": [
{
"id": "assistant.op.seo_read_project",
"capabilityId": "assistant.seo_read",
"sourceEndpoints": ["GET /seo/projects/:projectId"],
"requiredGuards": ["requireSeoProjectRead"],
"summary": "Read SEO project context through SEO-owned API."
},
{
"id": "assistant.op.seo_run_analysis",
"capabilityId": "assistant.seo_run_analysis",
"sourceEndpoints": ["POST /seo/projects/:projectId/scan", "POST /seo/projects/:projectId/analysis/semantic", "POST /seo/projects/:projectId/market/collect"],
"requiredGuards": ["requireSeoProjectWrite"],
"summary": "Run SEO scan and analysis through SEO-owned API."
},
{
"id": "assistant.op.seo_plan_changes",
"capabilityId": "assistant.seo_plan_changes",
"sourceEndpoints": ["POST /seo/projects/:projectId/anchor-review", "POST /seo/projects/:projectId/keyword-map", "POST /seo/projects/:projectId/optimization-plan", "POST /seo/projects/:projectId/rewrite-variants"],
"requiredGuards": ["requireSeoProjectWrite"],
"summary": "Prepare anchor review, curated keyword map, SEO plan and rewrite variants without mutating target source."
},
{
"id": "assistant.op.seo_apply_changes",
"capabilityId": "assistant.seo_apply_changes",
"sourceEndpoints": ["POST /seo/projects/:projectId/changesets/:changesetId/apply"],
"requiredGuards": ["requireSeoProjectApply", "requireSeoFinalValidation", "requireConfirmationToken", "requireIdempotencyKey"],
"summary": "Apply approved SEO changeset through SEO-owned adapter and safety gates."
}
]
}
@@ -0,0 +1,223 @@
{
"version": "0.1.0",
"updatedAt": "2026-07-02",
"apps": [
{
"id": "seo",
"name": "NDC SEO mod",
"authorityEntityIds": ["seo.project", "seo.site", "seo.scope_contract", "seo.change_set"],
"adapterId": "adapter.seo.module_api",
"summary": "Owns SEO project source/crawl, project ontology extraction, semantic analysis, market evidence, planning, validation, changesets, and apply/export."
}
],
"actions": [
{
"id": "seo.project.read_context",
"app": "seo",
"domain": "projects",
"intentAliases": ["show seo project", "show site seo context", "покажи seo проект", "покажи сео проект", "покажи контекст сайта"],
"entityIds": ["seo.project", "seo.site", "seo.scope_contract", "seo.project_ontology"],
"capabilityIds": ["assistant.seo_read"],
"riskLevel": "read",
"confirmationMode": "none",
"selfActionPolicy": "allowed",
"adapterId": "adapter.seo.module_api",
"adapterStatus": "future",
"summary": "Read SEO project context visible to the actor."
},
{
"id": "seo.project.scan",
"app": "seo",
"domain": "scan",
"intentAliases": ["scan seo project", "scan site", "run seo scan", "просканируй сайт", "запусти seo scan", "запусти скан сайта"],
"entityIds": ["seo.project", "seo.source", "seo.scan_version"],
"capabilityIds": ["assistant.seo_run_analysis"],
"riskLevel": "write",
"confirmationMode": "explicit",
"selfActionPolicy": "allowed",
"requiredScopes": ["seo.project.can_run_scan"],
"adapterId": "adapter.seo.module_api",
"adapterStatus": "future",
"summary": "Run SEO project scan and create a new scan_version artifact."
},
{
"id": "seo.ontology.extract",
"app": "seo",
"domain": "ontology",
"intentAliases": ["extract project ontology", "build site ontology", "определи онтологию сайта", "собери онтологию проекта"],
"entityIds": ["seo.project", "seo.project_ontology", "seo.semantic_profile"],
"capabilityIds": ["assistant.seo_run_analysis"],
"riskLevel": "write",
"confirmationMode": "explicit",
"selfActionPolicy": "allowed",
"requiredScopes": ["seo.project.can_run_analysis"],
"adapterId": "adapter.seo.module_api",
"adapterStatus": "future",
"summary": "Extract per-project site ontology from approved source/scope evidence."
},
{
"id": "seo.semantic.analyze",
"app": "seo",
"domain": "semantic",
"intentAliases": ["run semantic analysis", "analyze seo semantics", "проанализируй семантику", "запусти semantic analysis"],
"entityIds": ["seo.semantic_profile", "seo.intent_cluster", "seo.demand_universe", "seo.semantic_anchor"],
"capabilityIds": ["assistant.seo_run_analysis"],
"riskLevel": "write",
"confirmationMode": "explicit",
"selfActionPolicy": "allowed",
"requiredScopes": ["seo.project.can_run_analysis"],
"adapterId": "adapter.seo.module_api",
"adapterStatus": "future",
"summary": "Run semantic analysis bounded by ProjectOntologyInstance and scope contract."
},
{
"id": "seo.anchor_review.approve",
"app": "seo",
"domain": "market",
"intentAliases": ["approve seo anchors", "approve wordstat anchors", "зафиксируй ключи", "подтверди якоря", "зафиксируй смысловые якоря"],
"entityIds": ["seo.semantic_anchor", "seo.anchor_review", "seo.wordstat_queue"],
"capabilityIds": ["assistant.seo_plan_changes"],
"riskLevel": "write",
"confirmationMode": "explicit",
"selfActionPolicy": "allowed",
"requiredScopes": ["seo.project.can_collect_market_evidence"],
"adapterId": "adapter.seo.module_api",
"adapterStatus": "future",
"summary": "Create or update the human-approved anchor review and Wordstat queue before provider collection."
},
{
"id": "seo.market.collect_wordstat",
"app": "seo",
"domain": "market",
"intentAliases": ["collect wordstat", "run wordstat", "собери wordstat", "собери частотности", "запусти вордстат"],
"entityIds": ["seo.anchor_review", "seo.wordstat_queue", "seo.seed_query", "seo.market_signal", "seo.keyword"],
"capabilityIds": ["assistant.seo_run_analysis"],
"riskLevel": "write",
"confirmationMode": "explicit",
"selfActionPolicy": "allowed",
"requiredScopes": ["seo.project.can_collect_market_evidence"],
"adapterId": "adapter.seo.module_api",
"adapterStatus": "future",
"summary": "Collect Wordstat market evidence only for the human-approved Wordstat queue."
},
{
"id": "seo.keyword.curate",
"app": "seo",
"domain": "keywords",
"intentAliases": ["curate keywords", "sort keyword board", "распредели вес ключей", "разложи ключи", "отсортируй ключи"],
"entityIds": ["seo.keyword", "seo.keyword_curation_board", "seo.keyword_role_decision"],
"capabilityIds": ["assistant.seo_plan_changes"],
"riskLevel": "write",
"confirmationMode": "explicit",
"selfActionPolicy": "allowed",
"requiredScopes": ["seo.project.can_plan_changes"],
"adapterId": "adapter.seo.module_api",
"adapterStatus": "future",
"summary": "Pre-sort external keyword candidates into unresolved, landing core, supporting core, differentiators, or long tail lanes for human review."
},
{
"id": "seo.keyword.map",
"app": "seo",
"domain": "keywords",
"intentAliases": ["build keyword map", "map keywords", "собери keyword map", "распредели ключи", "составь карту ключей"],
"entityIds": ["seo.keyword", "seo.keyword_curation_board", "seo.keyword_role_decision", "seo.keyword_map", "seo.scope_item"],
"capabilityIds": ["assistant.seo_plan_changes"],
"riskLevel": "write",
"confirmationMode": "explicit",
"selfActionPolicy": "allowed",
"requiredScopes": ["seo.project.can_plan_changes"],
"adapterId": "adapter.seo.module_api",
"adapterStatus": "future",
"summary": "Build keyword map from curated keyword role decisions and approved scope items."
},
{
"id": "seo.mapping.approve",
"app": "seo",
"domain": "plan",
"intentAliases": ["approve landing mapping", "approve section mapping", "утверди посадочные", "утверди маппинг секций"],
"entityIds": ["seo.keyword_map", "seo.landing_section_mapping", "seo.future_landing_gap", "seo.scope_item"],
"capabilityIds": ["assistant.seo_plan_changes"],
"riskLevel": "write",
"confirmationMode": "explicit",
"selfActionPolicy": "allowed",
"requiredScopes": ["seo.project.can_plan_changes"],
"adapterId": "adapter.seo.module_api",
"adapterStatus": "future",
"summary": "Approve keyword landing/section mapping and keep future landing gaps non-blocking until explicit promotion."
},
{
"id": "seo.plan.build",
"app": "seo",
"domain": "plan",
"intentAliases": ["build optimization plan", "prepare seo plan", "собери план оптимизации", "подготовь seo план"],
"entityIds": ["seo.keyword_map", "seo.landing_section_mapping", "seo.future_landing_gap", "seo.optimization_plan", "seo.scope_contract"],
"capabilityIds": ["assistant.seo_plan_changes"],
"riskLevel": "write",
"confirmationMode": "explicit",
"selfActionPolicy": "allowed",
"requiredScopes": ["seo.project.can_plan_changes"],
"adapterId": "adapter.seo.module_api",
"adapterStatus": "future",
"summary": "Build SEO optimization plan before rewrite."
},
{
"id": "seo.rewrite.propose",
"app": "seo",
"domain": "rewrite",
"intentAliases": ["propose rewrite variants", "generate seo variants", "предложи варианты текста", "сгенерируй rewrite variants"],
"entityIds": ["seo.optimization_plan", "seo.rewrite_eligibility", "seo.semantic_block", "seo.rewrite_variant"],
"capabilityIds": ["assistant.seo_plan_changes"],
"riskLevel": "write",
"confirmationMode": "explicit",
"selfActionPolicy": "allowed",
"requiredScopes": ["seo.project.can_plan_changes"],
"adapterId": "adapter.seo.module_api",
"adapterStatus": "future",
"summary": "Generate rewrite variants into working draft only."
},
{
"id": "seo.validation.run",
"app": "seo",
"domain": "validation",
"intentAliases": ["run seo validation", "validate seo changes", "проверь seo изменения", "запусти финальную проверку"],
"entityIds": ["seo.validation_result", "seo.change_set", "seo.rewrite_variant"],
"capabilityIds": ["assistant.seo_plan_changes"],
"riskLevel": "write",
"confirmationMode": "explicit",
"selfActionPolicy": "allowed",
"requiredScopes": ["seo.project.can_validate_changes"],
"adapterId": "adapter.seo.module_api",
"adapterStatus": "future",
"summary": "Run final SEO validation before changeset apply/export."
},
{
"id": "seo.change_set.preview",
"app": "seo",
"domain": "changesets",
"intentAliases": ["preview seo changeset", "show seo diff", "покажи seo diff", "покажи changeset"],
"entityIds": ["seo.change_set", "seo.validation_result"],
"capabilityIds": ["assistant.seo_read"],
"riskLevel": "read",
"confirmationMode": "none",
"selfActionPolicy": "allowed",
"adapterId": "adapter.seo.module_api",
"adapterStatus": "future",
"summary": "Preview SEO changeset and validation state without applying changes."
},
{
"id": "seo.change_set.apply",
"app": "seo",
"domain": "changesets",
"intentAliases": ["apply seo changes", "apply seo changeset", "примени seo изменения", "примени changeset"],
"entityIds": ["seo.change_set", "seo.validation_result", "seo.apply_result"],
"capabilityIds": ["assistant.seo_apply_changes"],
"riskLevel": "write",
"confirmationMode": "explicit",
"selfActionPolicy": "allowed",
"requiredScopes": ["seo.project.can_apply_change_set"],
"adapterId": "adapter.seo.module_api",
"adapterStatus": "future",
"summary": "Apply an approved SEO changeset through SEO-owned adapter after validation, backup, idempotency, and explicit confirmation."
}
]
}
@@ -0,0 +1,35 @@
{
"version": "0.1.0",
"updatedAt": "2026-06-28",
"contexts": [],
"bindingTypes": [
{
"id": "binding_type.seo_project_to_ops_context",
"relationId": "ontology.resolves_seo_project_to_ops_context",
"fromEntityIds": ["seo.project"],
"toEntityIds": ["ops.project", "ops.card"],
"requiredFromRefs": ["seo_project_id"],
"requiredToRefs": ["workspace_slug", "project_id"],
"summary": "Binds an SEO project to its OPS Product project/card context."
},
{
"id": "binding_type.ops_context_to_seo_project",
"relationId": "ontology.resolves_ops_context_to_seo_project",
"fromEntityIds": ["ops.project", "ops.card"],
"toEntityIds": ["seo.project"],
"requiredFromRefs": ["workspace_slug", "project_id"],
"requiredToRefs": ["seo_project_id"],
"summary": "Binds OPS Product context to an SEO project."
},
{
"id": "binding_type.hub_app_to_seo_project",
"relationId": "ontology.resolves_hub_app_to_seo_project",
"fromEntityIds": ["hub.application"],
"toEntityIds": ["seo.project"],
"requiredFromRefs": ["application_id"],
"requiredToRefs": ["seo_project_id"],
"summary": "Binds a HUB/Launcher app entry to SEO module project context."
}
],
"bindings": []
}
@@ -0,0 +1,38 @@
{
"version": "0.1.0",
"updatedAt": "2026-07-02",
"entities": [
{ "id": "seo.project", "name": "SEO Project", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "SEO module project boundary for one connected site/source and its analysis history." },
{ "id": "seo.site", "name": "SEO Site", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "Analyzed website as seen through source import and/or live crawl." },
{ "id": "seo.source", "name": "SEO Source", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "Input source: local folder, uploaded package, browser-folder import, repository, or live URL crawl." },
{ "id": "seo.scan_version", "name": "SEO Scan Version", "surface": "seo", "status": ["source-evidenced"], "authority": "NDC SEO mod", "summary": "Immutable scan boundary for project index, pages, media, and derived scope." },
{ "id": "seo.scope_contract", "name": "SEO Scope Contract", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "User-approved working scope consumed consistently by analysis, planning, rewrite, validation, and apply." },
{ "id": "seo.scope_item", "name": "SEO Scope Item", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "One selectable work zone: URL page, generated section, template block, admin page, technical page, content source, or hidden section." },
{ "id": "seo.page", "name": "SEO Page", "surface": "seo", "status": ["source-evidenced"], "authority": "NDC SEO mod", "summary": "Logical page or route-level SEO target." },
{ "id": "seo.section", "name": "SEO Section", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "Stable section/block identity under a page or template, not a fragile DOM selector." },
{ "id": "seo.media_asset", "name": "SEO Media Asset", "surface": "seo", "status": ["source-evidenced"], "authority": "NDC SEO mod", "summary": "Image, video, poster, picture/srcset source, CSS background, or other media target with SEO metadata." },
{ "id": "seo.project_ontology", "name": "SEO Project Ontology Instance", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod + Ontology Core", "summary": "Versioned per-project site ontology extracted from evidence and aligned with Ontology Core." },
{ "id": "seo.semantic_profile", "name": "SEO Semantic Profile", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "Structured meaning, tone, entities, intents, gaps, and constraints extracted from selected scope." },
{ "id": "seo.intent_cluster", "name": "SEO Intent Cluster", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "Search/user intent cluster grounded in project ontology and site evidence." },
{ "id": "seo.demand_universe", "name": "SEO Demand Universe", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod + model provider", "summary": "Broad pre-Wordstat meaning and query hypothesis set derived from project context before external evidence collection." },
{ "id": "seo.semantic_anchor", "name": "SEO Semantic Anchor", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod + model provider", "summary": "Human-reviewable meaning anchor extracted from project context and used as the only allowed route into Wordstat/SERP queues." },
{ "id": "seo.anchor_review", "name": "SEO Anchor Review", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "Human approval gate that decides which semantic anchors may be sent to external market evidence providers." },
{ "id": "seo.wordstat_queue", "name": "SEO Wordstat Queue", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "Explicit queue of human-approved anchor phrases sent to Wordstat evidence collection." },
{ "id": "seo.seed_query", "name": "SEO Seed Query", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "Candidate phrase sent to market evidence providers after user/model review." },
{ "id": "seo.keyword", "name": "SEO Keyword", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "Cleaned and classified search phrase with project-level decision state." },
{ "id": "seo.market_signal", "name": "SEO Market Signal", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod + external providers", "summary": "Wordstat, SERP, Webmaster, Metrica, or model evidence attached to project-level decisions." },
{ "id": "seo.keyword_curation_board", "name": "SEO Keyword Curation Board", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "Human-in-the-loop board where external keyword candidates are sorted into SEO roles before strategy." },
{ "id": "seo.keyword_role_decision", "name": "SEO Keyword Role Decision", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "User/model-assisted role assignment for a keyword: unresolved, landing core, supporting core, differentiator, or long tail." },
{ "id": "seo.keyword_map", "name": "SEO Keyword Map", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "Approved mapping from keywords to pages/sections with roles and limits." },
{ "id": "seo.landing_section_mapping", "name": "SEO Landing Section Mapping", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "Human-approved mapping from curated keyword groups to existing pages, sections, or future landing gaps." },
{ "id": "seo.future_landing_gap", "name": "SEO Future Landing Gap", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "Non-blocking strategy gap for a potential future landing that must not be materialized or rewritten without explicit promotion." },
{ "id": "seo.optimization_plan", "name": "SEO Optimization Plan", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "Approved plan of text/meta/media/schema tasks before rewrite." },
{ "id": "seo.rewrite_eligibility", "name": "SEO Rewrite Eligibility", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "Gate proving that a rewrite target is an approved existing page/section/content-field binding rather than a future gap." },
{ "id": "seo.semantic_block", "name": "SEO Semantic Block", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "Persisted semantic grouping of page content targets used for block-level rewrite proposals." },
{ "id": "seo.rewrite_variant", "name": "SEO Rewrite Variant", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod + model provider", "summary": "Generated optimization variant over working text, not a direct source mutation." },
{ "id": "seo.validation_result", "name": "SEO Validation Result", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "Final validation output: deterministic checks, over-SEO, language quality, media checks, and hard/soft issues." },
{ "id": "seo.change_set", "name": "SEO Change Set", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "Explicit diff/apply unit with dry-run, backup, rollback, and export boundaries." },
{ "id": "seo.apply_result", "name": "SEO Apply Result", "surface": "seo", "status": ["product-required"], "authority": "NDC SEO mod", "summary": "Result of app-owned apply/export action after confirmation and validation." },
{ "id": "seo.expansion_opportunity", "name": "SEO Expansion Opportunity", "surface": "seo", "status": ["future-concept"], "authority": "NDC SEO mod", "summary": "Optional future coverage/growth suggestion after core analysis and market evidence, not part of the current ontology slice." }
]
}
@@ -0,0 +1,39 @@
{
"version": "0.1.0",
"updatedAt": "2026-07-02",
"sourceRoots": [
{
"surface": "seo",
"path": "/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_SEO/seo_mode/seo_mode",
"mode": "read-only architecture/source inspection"
}
],
"ledgers": [
{
"id": "ledger.seo_domain_v0",
"path": "docs/SEO_DOMAIN_ONTOLOGY.md",
"entityIds": [
"seo.project",
"seo.scope_contract",
"seo.project_ontology",
"seo.semantic_profile",
"seo.semantic_anchor",
"seo.anchor_review",
"seo.wordstat_queue",
"seo.market_signal",
"seo.keyword_curation_board",
"seo.landing_section_mapping",
"seo.future_landing_gap",
"seo.change_set"
]
}
],
"baselineDocs": [
"docs/SEO_DOMAIN_ONTOLOGY.md"
],
"restrictions": [
"Do not promote per-project SEO keywords or market rows into global ontology truth.",
"Do not let Ontology Core execute SEO source mutations.",
"Do not implement optional business expansion before core SEO pipeline evidence is proven."
]
}
@@ -0,0 +1,77 @@
{
"version": "0.1.0",
"updatedAt": "2026-07-02",
"rules": [
{
"id": "guardrail.seo.project_ontology_not_global_truth",
"severity": "error",
"summary": "Per-project SEO ontology is versioned project evidence; it must not be silently promoted into global Ontology Core truth.",
"entityIds": ["seo.project_ontology", "future.domain_package"]
},
{
"id": "guardrail.seo.keywords_are_project_evidence",
"severity": "error",
"summary": "Keywords, Wordstat rows, SERP rows, and forecasts are project evidence, not reusable ontology roots.",
"entityIds": ["seo.keyword", "seo.market_signal", "seo.project_ontology"]
},
{
"id": "guardrail.seo.scope_contract_required",
"severity": "error",
"summary": "Semantic analysis, keyword map, rewrite, validation, and changeset must be bounded by an approved scope contract.",
"entityIds": ["seo.scope_contract", "seo.scope_item", "seo.semantic_profile", "seo.change_set"]
},
{
"id": "guardrail.seo.wordstat_requires_anchor_review",
"severity": "error",
"summary": "Wordstat/SERP collection must use only human-approved semantic anchors from anchor review, never raw site text or model auto proposals.",
"entityIds": ["seo.semantic_anchor", "seo.anchor_review", "seo.wordstat_queue", "seo.market_signal"]
},
{
"id": "guardrail.seo.strategy_requires_curated_keywords",
"severity": "error",
"summary": "Strategy and optimization plan must consume curated keyword role decisions, not raw provider rows or unreviewed normalization output.",
"entityIds": ["seo.keyword_curation_board", "seo.keyword_role_decision", "seo.keyword_map", "seo.optimization_plan"]
},
{
"id": "guardrail.seo.future_landing_gap_non_blocking",
"severity": "error",
"summary": "Future landing gaps are strategy context only; they must not force materialization, rewrite, or random existing page selection without explicit promotion.",
"entityIds": ["seo.future_landing_gap", "seo.landing_section_mapping", "seo.rewrite_eligibility", "seo.rewrite_variant"]
},
{
"id": "guardrail.seo.rewrite_requires_existing_binding",
"severity": "error",
"summary": "Rewrite variants require approved existing page/section/content-field bindings and must not be generated for unresolved future gaps.",
"entityIds": ["seo.rewrite_eligibility", "seo.semantic_block", "seo.section", "seo.rewrite_variant"]
},
{
"id": "guardrail.seo.apply_requires_validation",
"severity": "error",
"summary": "SEO apply/export requires explicit changeset, final validation, dry-run/backup boundary, and app-owned adapter execution.",
"entityIds": ["seo.change_set", "seo.validation_result", "seo.apply_result", "assistant.action"]
},
{
"id": "guardrail.seo.ontology_core_does_not_apply",
"severity": "error",
"summary": "Ontology Core may resolve SEO action context but must not mutate site sources or execute SEO apply.",
"entityIds": ["seo.change_set", "assistant.action", "agent.scope", "agent.audit_event"]
},
{
"id": "guardrail.seo.expansion_is_future_optional_branch",
"severity": "warning",
"summary": "Expansion opportunities are a future optional branch after core analysis and market evidence; they must not replace current site context by default.",
"entityIds": ["seo.expansion_opportunity", "seo.market_signal", "seo.optimization_plan"]
}
],
"blockedConflations": [
["seo.project_ontology", "future.domain_package"],
["seo.keyword", "future.domain_package"],
["seo.semantic_anchor", "seo.market_signal"],
["seo.anchor_review", "seo.market_signal"],
["seo.market_signal", "seo.intent_cluster"],
["seo.keyword_curation_board", "seo.keyword_map"],
["seo.future_landing_gap", "seo.page"],
["seo.expansion_opportunity", "seo.optimization_plan"],
["seo.change_set", "assistant.action"]
]
}
@@ -0,0 +1,7 @@
{
"id": "seo",
"version": "0.1.0",
"updatedAt": "2026-06-28",
"status": "product-required/pending-source-pass",
"summary": "SEO module domain ontology package for site scans, project ontology, scope contracts, semantic analysis, market evidence, optimization plans, validation, and changesets."
}
@@ -0,0 +1,200 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://nodedc.local/ontology/seo/project-ontology.schema.json",
"title": "SEO Project Ontology Instance",
"type": "object",
"required": [
"schemaVersion",
"projectId",
"siteId",
"coreOntologyVersion",
"seoDomainPackageVersion",
"source",
"scope",
"brand",
"pages",
"sections",
"intentClusters",
"tone",
"constraints",
"evidence",
"approvals"
],
"additionalProperties": false,
"properties": {
"schemaVersion": { "const": "seo-project-ontology.v1" },
"projectId": { "type": "string", "minLength": 1 },
"siteId": { "type": "string", "minLength": 1 },
"coreOntologyVersion": { "type": "string", "minLength": 1 },
"seoDomainPackageVersion": { "type": "string", "minLength": 1 },
"source": {
"type": "object",
"required": ["sourceType", "scanVersionId"],
"additionalProperties": false,
"properties": {
"sourceType": {
"type": "string",
"enum": ["local_folder", "browser_folder", "uploaded_package", "repository", "live_crawl"]
},
"scanVersionId": { "type": "string", "minLength": 1 },
"rootUrl": { "type": ["string", "null"] },
"sourcePath": { "type": ["string", "null"] }
}
},
"scope": {
"type": "object",
"required": ["scopeContractId", "scopeItemIds"],
"additionalProperties": false,
"properties": {
"scopeContractId": { "type": "string", "minLength": 1 },
"scopeItemIds": {
"type": "array",
"items": { "type": "string", "minLength": 1 },
"uniqueItems": true
}
}
},
"brand": {
"type": "object",
"required": ["name", "aliases", "description"],
"additionalProperties": false,
"properties": {
"name": { "type": "string", "minLength": 1 },
"aliases": { "type": "array", "items": { "type": "string" } },
"description": { "type": "string" }
}
},
"offers": {
"type": "array",
"items": { "$ref": "#/$defs/namedEvidenceItem" }
},
"audiences": {
"type": "array",
"items": { "$ref": "#/$defs/namedEvidenceItem" }
},
"pages": {
"type": "array",
"items": {
"type": "object",
"required": ["id", "url", "title", "evidenceIds"],
"additionalProperties": false,
"properties": {
"id": { "type": "string", "minLength": 1 },
"url": { "type": "string" },
"title": { "type": "string" },
"evidenceIds": { "$ref": "#/$defs/evidenceIds" }
}
}
},
"sections": {
"type": "array",
"items": {
"type": "object",
"required": ["id", "pageId", "title", "meaning", "evidenceIds"],
"additionalProperties": false,
"properties": {
"id": { "type": "string", "minLength": 1 },
"pageId": { "type": "string", "minLength": 1 },
"title": { "type": "string" },
"meaning": { "type": "string" },
"evidenceIds": { "$ref": "#/$defs/evidenceIds" }
}
}
},
"intentClusters": {
"type": "array",
"items": {
"type": "object",
"required": ["id", "title", "priority", "targetIntent", "seedQueries", "evidenceIds"],
"additionalProperties": false,
"properties": {
"id": { "type": "string", "minLength": 1 },
"title": { "type": "string", "minLength": 1 },
"priority": { "type": "string", "enum": ["high", "medium", "low"] },
"targetIntent": { "type": "string" },
"seedQueries": {
"type": "array",
"items": { "type": "string", "minLength": 1 }
},
"evidenceIds": { "$ref": "#/$defs/evidenceIds" }
}
}
},
"tone": {
"type": "object",
"required": ["language", "signals", "forbiddenShifts"],
"additionalProperties": false,
"properties": {
"language": { "type": "string" },
"signals": { "type": "array", "items": { "type": "string" } },
"forbiddenShifts": { "type": "array", "items": { "type": "string" } }
}
},
"constraints": {
"type": "object",
"required": ["forbiddenTopics", "forbiddenClaims", "mustKeep"],
"additionalProperties": false,
"properties": {
"forbiddenTopics": { "type": "array", "items": { "type": "string" } },
"forbiddenClaims": { "type": "array", "items": { "type": "string" } },
"mustKeep": { "type": "array", "items": { "type": "string" } }
}
},
"evidence": {
"type": "array",
"items": {
"type": "object",
"required": ["id", "sourceType", "ref", "summary"],
"additionalProperties": false,
"properties": {
"id": { "type": "string", "minLength": 1 },
"sourceType": { "type": "string" },
"ref": { "type": "string" },
"summary": { "type": "string" }
}
}
},
"approvals": {
"type": "object",
"required": ["status", "approvedBy", "approvedAt"],
"additionalProperties": false,
"properties": {
"status": { "type": "string", "enum": ["draft", "approved", "rejected", "needs_review"] },
"approvedBy": { "type": ["string", "null"] },
"approvedAt": { "type": ["string", "null"] }
}
},
"ontologyDeltaProposals": {
"type": "array",
"items": {
"type": "object",
"required": ["id", "target", "summary", "status"],
"additionalProperties": false,
"properties": {
"id": { "type": "string", "minLength": 1 },
"target": { "type": "string", "enum": ["core", "seo_domain", "project_only"] },
"summary": { "type": "string" },
"status": { "type": "string", "enum": ["proposed", "accepted", "rejected", "deferred"] }
}
}
}
},
"$defs": {
"evidenceIds": {
"type": "array",
"items": { "type": "string", "minLength": 1 },
"uniqueItems": true
},
"namedEvidenceItem": {
"type": "object",
"required": ["id", "name", "summary", "evidenceIds"],
"additionalProperties": false,
"properties": {
"id": { "type": "string", "minLength": 1 },
"name": { "type": "string", "minLength": 1 },
"summary": { "type": "string" },
"evidenceIds": { "$ref": "#/$defs/evidenceIds" }
}
}
}
}
@@ -0,0 +1,47 @@
{
"version": "0.1.0",
"updatedAt": "2026-07-02",
"relations": [
{ "id": "seo.project.has_site", "from": ["seo.project"], "to": ["seo.site"], "status": "product-required", "summary": "SEO project analyzes one or more site contexts." },
{ "id": "seo.project.uses_source", "from": ["seo.project"], "to": ["seo.source"], "status": "product-required", "summary": "SEO project is connected to import/crawl source." },
{ "id": "seo.project.has_project_ontology", "from": ["seo.project"], "to": ["seo.project_ontology"], "status": "product-required", "summary": "Per-project ontology profile belongs to SEO project." },
{ "id": "seo.source.produces_scan_version", "from": ["seo.source"], "to": ["seo.scan_version"], "status": "product-required", "summary": "Source import/crawl creates immutable scan version." },
{ "id": "seo.scan_version.produces_scope_contract", "from": ["seo.scan_version"], "to": ["seo.scope_contract"], "status": "product-required", "summary": "Scan and user configuration produce approved scope contract." },
{ "id": "seo.scope_contract.contains_scope_item", "from": ["seo.scope_contract"], "to": ["seo.scope_item"], "status": "product-required", "summary": "Scope contract is composed of selected work zones." },
{ "id": "seo.scope_item.targets_page", "from": ["seo.scope_item"], "to": ["seo.page"], "status": "product-required", "summary": "Scope item can target a logical page." },
{ "id": "seo.scope_item.targets_section", "from": ["seo.scope_item"], "to": ["seo.section"], "status": "product-required", "summary": "Scope item can target a stable section/block." },
{ "id": "seo.site.has_page", "from": ["seo.site"], "to": ["seo.page"], "status": "product-required", "summary": "Site contains logical pages/routes." },
{ "id": "seo.page.has_section", "from": ["seo.page"], "to": ["seo.section"], "status": "product-required", "summary": "Page can contain stable sections/blocks." },
{ "id": "seo.section.contains_media", "from": ["seo.section"], "to": ["seo.media_asset"], "status": "product-required", "summary": "Media is attached to a section when context can be resolved." },
{ "id": "seo.semantic_profile.uses_project_ontology", "from": ["seo.semantic_profile"], "to": ["seo.project_ontology"], "status": "product-required", "summary": "Semantic analysis is grounded in per-project ontology." },
{ "id": "seo.semantic_profile.describes_scope_contract", "from": ["seo.semantic_profile"], "to": ["seo.scope_contract"], "status": "product-required", "summary": "Semantic profile describes selected work scope, not arbitrary site fantasy." },
{ "id": "seo.semantic_profile.produces_demand_universe", "from": ["seo.semantic_profile"], "to": ["seo.demand_universe"], "status": "product-required", "summary": "Selected project context produces a broad demand universe before provider calls." },
{ "id": "seo.demand_universe.contains_semantic_anchor", "from": ["seo.demand_universe"], "to": ["seo.semantic_anchor"], "status": "product-required", "summary": "Demand universe contains semantic anchors that can be reviewed for market routing." },
{ "id": "seo.semantic_anchor.requires_anchor_review", "from": ["seo.semantic_anchor"], "to": ["seo.anchor_review"], "status": "product-required", "summary": "A semantic anchor cannot enter Wordstat/SERP routing before human anchor review." },
{ "id": "seo.anchor_review.approves_wordstat_queue", "from": ["seo.anchor_review"], "to": ["seo.wordstat_queue"], "status": "product-required", "summary": "Anchor review creates the explicit Wordstat queue from approved anchors." },
{ "id": "seo.intent_cluster.suggests_seed_query", "from": ["seo.intent_cluster"], "to": ["seo.seed_query"], "status": "product-required", "summary": "Intent cluster can suggest seed queries for evidence collection." },
{ "id": "seo.wordstat_queue.contains_seed_query", "from": ["seo.wordstat_queue"], "to": ["seo.seed_query"], "status": "product-required", "summary": "Only human-approved Wordstat queue items become executable seed queries." },
{ "id": "seo.wordstat_queue.produces_market_signal", "from": ["seo.wordstat_queue"], "to": ["seo.market_signal"], "status": "product-required", "summary": "Wordstat collection stores provider results as market signals tied to the approved queue." },
{ "id": "seo.seed_query.expands_to_keyword", "from": ["seo.seed_query"], "to": ["seo.keyword"], "status": "product-required", "summary": "Approved seed query can produce cleaned keyword candidates." },
{ "id": "seo.keyword.validated_by_market_signal", "from": ["seo.keyword"], "to": ["seo.market_signal"], "status": "product-required", "summary": "Keyword decisions require market evidence when available." },
{ "id": "seo.keyword_curation_board.classifies_keyword", "from": ["seo.keyword_curation_board"], "to": ["seo.keyword_role_decision", "seo.keyword"], "status": "product-required", "summary": "Keyword curation board assigns human-reviewed roles to keyword candidates." },
{ "id": "seo.keyword_role_decision.produces_keyword_map", "from": ["seo.keyword_role_decision"], "to": ["seo.keyword_map"], "status": "product-required", "summary": "Only curated keyword role decisions can feed the keyword map used by strategy." },
{ "id": "seo.keyword_map.assigns_keyword", "from": ["seo.keyword_map"], "to": ["seo.keyword", "seo.scope_item"], "status": "product-required", "summary": "Keyword map assigns keywords to approved scope items." },
{ "id": "seo.keyword_map.requires_landing_section_mapping", "from": ["seo.keyword_map"], "to": ["seo.landing_section_mapping"], "status": "product-required", "summary": "Keyword map must be resolved to approved existing pages/sections or explicit future gaps before rewrite." },
{ "id": "seo.landing_section_mapping.maps_keyword_to_scope_item", "from": ["seo.landing_section_mapping"], "to": ["seo.keyword", "seo.scope_item"], "status": "product-required", "summary": "Landing/section mapping binds curated keywords to existing approved scope items." },
{ "id": "seo.landing_section_mapping.identifies_future_gap", "from": ["seo.landing_section_mapping"], "to": ["seo.future_landing_gap"], "status": "product-required", "summary": "A mapping can explicitly mark a keyword group as a non-blocking future landing gap." },
{ "id": "seo.optimization_plan.uses_keyword_map", "from": ["seo.optimization_plan"], "to": ["seo.keyword_map"], "status": "product-required", "summary": "Optimization plan is based on approved keyword map." },
{ "id": "seo.optimization_plan.targets_scope_contract", "from": ["seo.optimization_plan"], "to": ["seo.scope_contract"], "status": "product-required", "summary": "Optimization plan targets approved scope contract." },
{ "id": "seo.rewrite_eligibility.requires_landing_section_mapping", "from": ["seo.rewrite_eligibility"], "to": ["seo.landing_section_mapping"], "status": "product-required", "summary": "Rewrite eligibility requires an approved mapping to an existing source-backed target." },
{ "id": "seo.semantic_block.groups_section", "from": ["seo.semantic_block"], "to": ["seo.section", "seo.scope_item"], "status": "product-required", "summary": "Semantic blocks group source-backed sections/scope items for block-level rewrite proposals." },
{ "id": "seo.rewrite_variant.requires_rewrite_eligibility", "from": ["seo.rewrite_variant"], "to": ["seo.rewrite_eligibility", "seo.semantic_block"], "status": "product-required", "summary": "Rewrite variants can be proposed only for eligible existing bindings, optionally grouped by semantic block." },
{ "id": "seo.rewrite_variant.generated_from_plan", "from": ["seo.rewrite_variant"], "to": ["seo.optimization_plan"], "status": "product-required", "summary": "Rewrite variant is generated from approved optimization plan." },
{ "id": "seo.validation_result.validates_change_set", "from": ["seo.validation_result"], "to": ["seo.change_set"], "status": "product-required", "summary": "Change set must be validated before apply." },
{ "id": "seo.change_set.applies_to_scope_contract", "from": ["seo.change_set"], "to": ["seo.scope_contract"], "status": "product-required", "summary": "Change set is bounded by approved scope contract." },
{ "id": "seo.change_set.produces_apply_result", "from": ["seo.change_set"], "to": ["seo.apply_result"], "status": "product-required", "summary": "Apply/export produces a traceable result." },
{ "id": "seo.expansion_opportunity.requires_market_signal", "from": ["seo.expansion_opportunity"], "to": ["seo.market_signal"], "status": "future-concept", "summary": "Future expansion proposals must be grounded in market evidence." },
{ "id": "ontology.resolves_seo_project_to_ops_context", "from": ["seo.project"], "to": ["ops.project", "ops.card"], "status": "product-required", "summary": "Assistant can route SEO project work to the correct OPS Product context." },
{ "id": "ontology.resolves_ops_context_to_seo_project", "from": ["ops.project", "ops.card"], "to": ["seo.project"], "status": "product-required", "summary": "Assistant can route OPS Product context into SEO module project context when bound." },
{ "id": "ontology.resolves_hub_app_to_seo_project", "from": ["hub.application"], "to": ["seo.project"], "status": "product-required", "summary": "Launcher/HUB application context can suggest SEO module project context." }
]
}
@@ -0,0 +1,42 @@
{
"version": "0.1.0",
"updatedAt": "2026-06-28",
"rules": [
{
"id": "resolver.seo_to_ops.project_context",
"relationId": "ontology.resolves_seo_project_to_ops_context",
"fromSurface": "seo",
"inputEntityIds": ["seo.project", "seo.site", "seo.scope_contract"],
"intentHints": ["ops", "card", "task", "issue", "project", "report", "карточ", "задач", "отчет"],
"outputSurface": "ops",
"outputEntityIds": ["ops.workspace", "ops.project", "ops.card", "ops.card_type"],
"requiredBindings": ["seo.project -> ops.project|ops.card context"],
"status": "product-required",
"summary": "Route SEO module project context into OPS Product work context."
},
{
"id": "resolver.ops_to_seo.project_context",
"relationId": "ontology.resolves_ops_context_to_seo_project",
"fromSurface": "ops",
"inputEntityIds": ["ops.project", "ops.card"],
"intentHints": ["seo", "site", "semantic", "wordstat", "keyword", "rewrite", "validation", "сео", "сайт", "семантик"],
"outputSurface": "seo",
"outputEntityIds": ["seo.project", "seo.site", "seo.scope_contract", "seo.project_ontology"],
"requiredBindings": ["ops.project|ops.card -> seo.project context"],
"status": "product-required",
"summary": "Route OPS Product context into SEO module project context."
},
{
"id": "resolver.hub_app_to_seo.project_context",
"relationId": "ontology.resolves_hub_app_to_seo_project",
"fromSurface": "hub",
"inputEntityIds": ["hub.application"],
"intentHints": ["seo", "site", "project", "audit", "сео", "сайт", "аудит"],
"outputSurface": "seo",
"outputEntityIds": ["seo.project", "seo.site"],
"requiredBindings": ["hub.application -> seo.project context"],
"status": "product-required",
"summary": "Route Launcher app context into SEO module project context."
}
]
}