Summary
src/intelligence/SeoBuildIntelligencePort.ts defines the SEO build-intelligence seam, but nothing implements it and nothing calls it. It is a contract surface with no runtime behind it. Separately, four of its request fields do not match the live SEO-Bot endpoint schemas, so a naive adapter written against it would be rejected at the boundary.
Observed at Website-Bot 70f3f9a4, SEO-Bot 519879e6.
The seam is inert
$ grep -rn "implements SeoBuildIntelligencePort\|SeoBuildIntelligencePort" src/ scripts/ tests/
src/intelligence/SeoBuildIntelligencePort.ts:47:export interface SeoBuildIntelligencePort {
tests/unit/seo-build-intelligence-port.test.ts:12:import { assertWebsiteBlueprintLandscape } from ...
$ grep -rn "build-intelligence" src/ scripts/
(no matches)
Zero implementations, zero call sites, and no code anywhere references the three endpoints. compilePageContentContract (src/intelligence/compile-page-content-contract.ts) is correctly deterministic and zero-LLM — and also has no caller.
Contract mismatches vs. live SEO-Bot
SEO-Bot's request bodies are z.object({...}).strict() (SEO-Bot/src/api/build-intelligence.ts:60-101), so extra or wrongly-typed fields are a hard 400, not a coercion.
| Field |
Website-Bot port |
SEO-Bot schema |
Result |
seed_queries |
string[] |
Array<{query, intent, weight?}> |
incompatible — 400 |
desired_donor_count |
required |
optional (default 10) |
over-constrained |
market.device |
required |
optional |
over-constrained |
operator_exclusions |
absent |
supported |
capability lost |
seo_config |
absent |
supported |
capability lost |
The intent discriminator is not decorative: competitive-landscape.ts uses it to build the query portfolio, and weight feeds visibilityContribution(weight, rank). Flattening to string[] discards the ranking-truth inputs.
Auth
Build-intelligence routes are not auth-exempt (SEO-Bot/src/api/security.ts — exempt list is /health and /api/clients/register only). Operator auth accepts Bearer <token> or HTTP Basic (password portion), compared constant-time against OPERATOR_API_KEY. Fail-closed: if OPERATOR_API_KEY is unset, every protected route returns 401.
Expected
A single canonical real adapter (SeoBuildIntelligenceHttpAdapter or repo-native equivalent) performing authenticated HTTP against:
POST /api/build-intelligence/competitive-landscape
POST /api/build-intelligence/seo-content-blueprint
POST /api/build-intelligence/structured-content
with typed requests/responses, timeout, bounded retries only where safe, fail-closed auth and malformed-response handling, artifact schema validation, ArtifactRef validation, payload-digest validation, and exact input-lineage validation. No provider/model/temperature/raw-prompt fields in application requests (SEO-Bot's .strict() bodies already reject these at the boundary — the adapter must not attempt them).
Port request types must be corrected to the five points above first, or the adapter cannot typecheck against reality.
Explicitly not an SEO-Bot defect
SEO-Bot's side of this seam is correct and needs no change. The mismatch is entirely in the Website-Bot port declaration.
Summary
src/intelligence/SeoBuildIntelligencePort.tsdefines the SEO build-intelligence seam, but nothing implements it and nothing calls it. It is a contract surface with no runtime behind it. Separately, four of its request fields do not match the live SEO-Bot endpoint schemas, so a naive adapter written against it would be rejected at the boundary.Observed at Website-Bot
70f3f9a4, SEO-Bot519879e6.The seam is inert
Zero implementations, zero call sites, and no code anywhere references the three endpoints.
compilePageContentContract(src/intelligence/compile-page-content-contract.ts) is correctly deterministic and zero-LLM — and also has no caller.Contract mismatches vs. live SEO-Bot
SEO-Bot's request bodies are
z.object({...}).strict()(SEO-Bot/src/api/build-intelligence.ts:60-101), so extra or wrongly-typed fields are a hard 400, not a coercion.seed_queriesstring[]Array<{query, intent, weight?}>desired_donor_countmarket.deviceoperator_exclusionsseo_configThe
intentdiscriminator is not decorative:competitive-landscape.tsuses it to build the query portfolio, and weight feedsvisibilityContribution(weight, rank). Flattening tostring[]discards the ranking-truth inputs.Auth
Build-intelligence routes are not auth-exempt (
SEO-Bot/src/api/security.ts— exempt list is/healthand/api/clients/registeronly). Operator auth acceptsBearer <token>or HTTPBasic(password portion), compared constant-time againstOPERATOR_API_KEY. Fail-closed: ifOPERATOR_API_KEYis unset, every protected route returns 401.Expected
A single canonical real adapter (
SeoBuildIntelligenceHttpAdapteror repo-native equivalent) performing authenticated HTTP against:POST /api/build-intelligence/competitive-landscapePOST /api/build-intelligence/seo-content-blueprintPOST /api/build-intelligence/structured-contentwith typed requests/responses, timeout, bounded retries only where safe, fail-closed auth and malformed-response handling, artifact schema validation,
ArtifactRefvalidation, payload-digest validation, and exact input-lineage validation. No provider/model/temperature/raw-prompt fields in application requests (SEO-Bot's.strict()bodies already reject these at the boundary — the adapter must not attempt them).Port request types must be corrected to the five points above first, or the adapter cannot typecheck against reality.
Explicitly not an SEO-Bot defect
SEO-Bot's side of this seam is correct and needs no change. The mismatch is entirely in the Website-Bot port declaration.