mainWhat we shipped.
One line per merged pull request, dated by merge day. Generated by the same automation that pushes the code, so the only delay between "we shipped it" and "it appears here" is a CI run.
What changed most recently in VectraSEO?
The changelog lists the latest merged pull requests by release date, with the newest shipped change first and older releases kept in the project archive.
Last updated·
- PR_1839CHANGEDfix(truth): dead vendor links drop their claim; unnamed own-product prose sees own evidence
Follow-up to the 2026-10-09 overdue-posts investigation, issue #2 (Iceland Photo Map,
proj_ab5ead538b5947e7) plus one leftover from #3. - PR_1837CHANGEDfix(eval): grade repair through production's whole repair step
The DeepSeek route eval (
model_ab_eval --candidate) failed content_repair on both routes: Gemini passed the gate on 4 of 14 cases and DeepSeek on 1 of 14 (2026-10-09). The... - PR_1834CHANGEDfix(gemini): label default-model calls in gemini_usage
The Oct 9 Gemini cost review found 325 Flash calls ($19.43, 25% of the week's spend) with
task: nullingemini_usage. All of them came from post-generation lineages (`ga... - PR_1833CHANGEDfix(truth): name the business's own table column; extractor knows an unnamed one
Iceland Photo Map, 2026-10-08 (
post_4f2cf81e5dd841f9): the comparison table was headedGoogle Maps | OsmAnd | Curated Waypoint Files. The last column was the business's own... - PR_1830CHANGEDfix(truth): a sentence pointing at the business's own site gets its evidence
Iceland Photo Map, post_4f2cf81e5dd841f9 (2026-10-08): *"The free sample at /sample is five real waypoints from the catalog, in the same fo...
- PR_1826CHANGEDfix(truth): automatic recovery judges own-product claims with the Content Brief
Iceland Photo Map (proj_ab5ead538b5947e7) lost two scheduled drafts on 2026-10-08 and 10-09 over "$14 per map". The price is in the static HTML of
/maps/Waterfall. - PR_1827CHANGEDfix(truth): other-product holds — dead search URLs, irregular table rows, table-cell rule
Iceland Photo Map (
proj_ab5ead538b5947e7) lost four drafts across two topics on 2026-10-08/09. All four endedarchived_unsalvageableon the truth gate, with 35 blocking clai... - PR_1825CHANGEDfix(lint): "do not publish" is a label, not a phrase; repair drafting notes
2026-10-08: a Vectra SEO scheduled post told its reader *"If you cannot point to a verifiable source for a claim, do not publish it."* The publish lint matched
do not publish... - PR_1823CHANGEDfix(schedule): worked examples aren't uncited claims; overdue card says why
On 2026-10-09, 5 of 20 scheduled projects showed Scheduled post overdue. The scheduler had fired on time for every one. In each case the draft was held by a publish gate, fa...
- PR_1821CHANGEDdocs(traffic): publish sender guidance on the public ingest docs
PR #1819 added three details to the internal
docs/traffic-ingest.md. None of them was on the public page senders read (/docs/provisioning#first-party-traffic, which the in-a... - PR_1819CHANGEDdocs(traffic): define visits, render-signal guidance, filter probe paths
Docs only. Came out of the tempkey / echothread integrations after #1817.
- PR_1817CHANGEDfix(traffic): count only 2xx human requests as first-party visits
EchoThread's card showed 3,560 "Other visits (site logs)" over Oct 4-7. Nearly all of it was monitors, scanners, QA runs and redirect hops. EchoThread is fixing its own classifi...
- PR_1815CHANGEDfix(waf): exempt /traffic/daily ingest from CRS GenericLFI_BODY only
POST /api/v1/projects/{id}/traffic/dailybodies are customer access-log rollups. They contain scanner probe paths such as/.htpasswdand/app/etc/local.xmlas data. `A... - PR_1813CHANGEDfeat(traffic): file self_referrer feed rows as internal, never counted
- PR_1811CHANGEDfix(recovery): an unresolved attempt returns an archived post to archived
vectraseo-prod-stranded-postshas been in ALARM continuously since 2026-09-26 (gauge 5–7 on every sweep).
- PR_1808CHANGEDfeat(posts): owner-declared superseded-post marker
A site owner can consolidate one of our published posts into another and 301 the old URL to the survivor. One example is EchoThread
post_8bc373fb1ee54d0b→ `post_b1f4514dcf074... - PR_1807CHANGEDfix(indexing): enable Indexing API flag on the workers; warn when skipped
Google Indexing API (Tier 2) has never fired on publish for any project.
INDEXING_API_ENABLED=trueis set on the API Lambda (api_stack.py), but publish-timeURL_UPDATEDru... - PR_1805CHANGEDfix(truth): confirm verbatim capability-file copies; lint dash-hung directives
The EchoThread drafts on 10-02 and 10-04 were held by our own gates. EchoThread's endpoint received nothing, because these posts were never sent. Two of the causes are on our side:
- PR_1803CHANGEDfeat(traffic): detailed Traffic panel on the project page
Follows #1801 (merged).
- PR_1801CHANGEDfix(traffic): name every bar segment; compare GA with all Google search clicks
Follow-up to #1799 after checking the Alaska Road Trip and Emcognito cards.
- PR_1799CHANGEDfeat(traffic): card adds Search Console clicks to site logs for one total
sendant.io (site logs, no GA4) stopped showing Google Search traffic on its project card. The headline was 2 visits (site logs) for 1 of 28 logged days, and the 178 Search C...
- PR_1797CHANGEDfeat(keys): project-restricted account keys + bind scan ids to their monitor
Account keys (
vsak_) span every project the owner has. The Search tab's site-logs "Create a key" link minted a key named after one site ("EchoThread site logs") that could act... - PR_1795CHANGEDSite logs setup panel + project card shows a new CloudFront feed at once
Connecting a site's own access logs (first-party traffic ingest) had no in-app surface, and once sendant.io's first CloudFront day landed the project card still read **"Search C...
- PR_1791CHANGEDfix: consistent reads for the remaining read-after-write sites
Follow-up to #1771. A default DynamoDB GetItem/Query is eventually consistent. A read that lands milliseconds after a write can see the row as it was before the write, or no row...
- PR_1790CHANGEDfix(indexnow): cooldown on key-file check + first-writer-wins key mint
Hardens the IndexNow settings endpoints added in #1765 and #1782.
- PR_1789CHANGEDtest(blog_service): raise coverage 88% -> 94% with repair failure-path tests
Test-only PR. Adds 48 behavioral tests for
backend/app/services/blog_service.py, covering uncovered error, fallback and budget-checkpoint branches that feed `_combined_post_st... - PR_1787CHANGEDfix(scripts): repair malformed monitor sitemap URLs in the URL backfill
scripts/fix_malformed_site_urls.pyonly reads project#METADATArows. Projectproj_23c433aa19484c6ealready had itssitemap_urlcorrected, but its monitor `mon_dcf0137d1... - PR_1781CHANGEDdocs(ia): split /docs into a hub + per-chapter URLs
Audit PR-10 (
docs-coverage-audit.md§c): the public docs were one ~3,900-line SPA page with hash anchors, one indexable URL and no search. - PR_1782CHANGEDfix(indexing): IndexNow QA follow-ups to #1765
QA follow-ups for #1765 (merged while QA was running). Each fix has a regression test that fails on current main.
- PR_1778CHANGEDfix: QA follow-ups to #1770 - never strip unconfirmed links; ResolverError 500s
QA follow-ups to #1770 (merged while QA was still running). Opened as a draft so it is not auto-merged before review.
- PR_1780CHANGEDbuild(deps-dev): Bump brace-expansion from 1.1.18 to 1.1.21 in /frontend
Bumps brace-expansion from 1.1.18 to 1.1.21.
- PR_1771CHANGEDfix(publish): consistent read for just-written posts; swept crashes are not terminal
Nightlamp
bulk_publish_failed+pipeline_publish_partial_failed(high), 2026-10-04T00:08:03Z, projectproj_d8a14f17a9b74602, jobjob_ddd3ae50e00542fb, post `post_22f8fa3... - PR_1776CHANGEDbuild(deps): Bump axios from 1.18.0 to 1.20.0 in /frontend
Bumps axios from 1.18.0 to 1.20.0.
- PR_1766CHANGEDfix(claims): stop exponential backtracking that hung phase_advance to the 900s kill
Nightlamp's only unresolved issue cluster (26 issues, one per stack-dump line) was the
hang_tracebackdump from twophase_advancekills on 2026-10-04 (05:58Z, 06:43Z), both... - PR_1777CHANGEDbuild(deps): Bump dompurify from 3.4.13 to 3.4.16 in /frontend
Bumps dompurify from 3.4.13 to 3.4.16.
- PR_1768CHANGEDci: run every workflow job on the self-hosted fleet
Requirement: every GitHub Actions job runs on the org's self-hosted runners.
- PR_1767CHANGEDfix(dynamodb): give boto3's expression builder per-thread state
recommendation_page_summary_lookup_failedhas fired 6 times on the API Lambda since 2026-07-14. The latest was 2026-10-03T20:29:41Z onproj_97de1a48214244b9: - PR_1765CHANGEDfix(indexing): send IndexNow only for a key proven on the post's own host
IndexNow (the Bing/Yandex ping in the default-on Tier 1 indexing signals) has never fired in production. Meanwhile the Settings toggle says "we … notify Bing & Yandex via IndexN...
- PR_1770CHANGEDfix: treat getaddrinfo EBUSY as unverified; shape-check onboarding URLs
Two production findings, investigated with read-only access (CloudWatch Logs Insights, one DynamoDB GetItem/Query, and a
--dry-runof the backfill script). - PR_1764CHANGEDdocs: AI Visibility, Rank Tracker and FAQ chapters on /docs
Docs-only (PR-14 in the docs coverage audit, plus the Visibility/Ranks chapters). No backend behaviour changes.
- PR_1763CHANGEDfeat(marketing): /guides feature guide pages + index
Adds the PR-13 feature guides from the docs-coverage audit. These are
/guides/pages that double as landing pages, covering only features that are live in production: - PR_1760CHANGEDfeat(ui): in-app "Learn how" docs links + /seo explainers for sitemap_hygiene and merchant_listing
Covers PR-9 and PR-12 from the docs coverage audit.
- PR_1759CHANGEDseo(aeo): expand llms.txt / llms-full.txt to the developer surface and Local Scout
PR-11 from the public-docs coverage audit. Before this,
llms.txtlisted seven pages and none of the developer surface (no MCP, Provisioning API, Analytics API or agent feed),... - PR_1756CHANGEDdocs(public): product chapters for fixes, Search Console, content pipeline and Custom API v2
Adds customer-facing chapters to
/docs(frontend/src/views/DocsView.vue), as new sections plus TOC/chapter entries, so the merge with the concurrentapiGroupsrewrite stay... - PR_1755CHANGEDdocs(public): generated API reference with per-route scope and plan
The REST reference on
/docswas a list kept by hand. It is now generated from FastAPI's route table, so a new route cannot ship without showing up there. This is PR-3 and PR-8... - PR_1752CHANGEDdocs(public): fix wrong routes, issue shape, severities and stale limits
Fixes every WRONG item the public-docs coverage audit found. I re-checked each one against
origin/mainbefore changing it. No backend behaviour changes. The only backend file... - PR_1751CHANGEDfix(metrics): log the lane EMF line as info, not an error
Nightlamp opened a level=error, severity=high issue for a routine metric line from PipelineWorker:
- PR_1748CHANGEDdocs(public): document first-party traffic ingest on /docs
https://vectraseo.com/docs lists the
traffic:writescope but none of the endpoints it unlocks. A customer can mint the key and still not know what to call or send. The full co... - PR_1747CHANGEDfeat(pipeline): spread the scheduler tick and split the queue into lanes (ADR-0005)
Production numbers for 2026-09-27 to 10-04 (ADR-0005,
docs/adr/0005-pipeline-scale-spread-and-lanes.md): - PR_1745CHANGEDfix(worker): stop the SQS poller at the worker's concurrency cap
vectraseo-prod-pipeline-worker-throttleswent to ALARM on 2026-10-04 at 01:06Z. The first scheduler tick after #1737 deployed sent out all 19 catch-up GSC syncs at once. The p... - PR_1742CHANGEDfeat(projects): first-party visits on the project card when GA4 has no data
When a project has no usable GA4 (not connected, or
ga4_traffic_summarywith 0 sessions) but does push first-party traffic viaPOST /traffic/daily, the project card'... - PR_1739CHANGEDperf(projects): serve the card's opportunity count from a stored copy
The
vectraseo-prod-api-lambda-p99-durationalarm (2026-10-03 23:51 UTC, p99 10.1–10.7s) traced toGET /projects/list-summary. Profiling 21 real projects read-only showed it... - PR_1737CHANGEDfix(projects): fill traffic cards after deploy, handle empty GA4, restore QA fixes
After #1733 deployed, the traffic cards kept showing Search Console only, and two cards showed 0 visits once they synced.
- PR_1738CHANGEDperf(api): raise API Lambda to 1024 MB for CPU-bound card loads
vectraseo-prod-api-lambda-p99-durationfired at 23:51 UTC on 2026-10-03 (p99 10.1s, then 10.7s).
- PR_1735CHANGEDfeat(traffic): first-party traffic ingest (customer-pushed CDN log rollups)
VectraSEO only learns about traffic by pulling GSC and GA4 over OAuth. sendant.io (
proj_63b11d19aa2b4fd7) has neither, and it promises no analytics. This PR adds a second way... - PR_1733CHANGEDfeat(projects): all-channel traffic on the project card (GA4 + Search Console)
The project card's Search Console block becomes a Traffic block:
- PR_1731CHANGEDtest(worker): pin the hang stack dump to the pipeline handler
Follow-up to #1729.
- PR_1729CHANGEDfix(worker): dump all thread stacks 30s before a Lambda timeout-kill
The pipeline worker hit its 900s Lambda limit 6 times between 2026-09-24 and 2026-10-01. There were none between Sep 6 and Sep 23. Each hit blocks that project's FIFO group for...
- PR_1727CHANGEDfix(budget): don't charge a redo of yesterday's post to today's slot
The daily post budget (
_get_remaining_posts_budget) counts unarchived posts created since UTC midnight. When a late-evening run's post is regenerated, or replaced by a hel... - PR_1725CHANGEDfix(claim-strip): drop figures a capability strip left without their citation
Since the capability gate (
084ac618, 2026-09-21) went live, the truth first-pass rate fell from about 0.42 to 0.18. Among first-fail posts, regenerations went from 2 to 45. 15... - PR_1723CHANGEDfix(canary): report every guardrail metric that breaches in a window
The 2026-10-03
canary_guardrail_breachalert foroutline(day 2026-10-02) reported onlypublish_rate(0.906 vs 1.130).window_breachreturns the first breaching metric,... - PR_1721CHANGEDfeat(admin): redesign /admin/signups
Restyles the owner-only
/admin/signupspage within the existing ops design language (--ops-*tokens, Fraunces, IBM Plex). Data flow, API calls and filter semantics are uncha... - PR_1719CHANGEDtest: block real HTTP in the backend suite (#1714)
Every backend test run made about 108 real outbound requests: example.com robots.txt and llms.txt, evil.com, Gemini (
generateContentwith a dummy key), Search Console, Shopify... - PR_1712CHANGEDfeat(admin): richer per-account detail on /admin/signups
/admin/signupsnow shows who each account is and how far it got. Before, most rows read "Historical / unknown". - PR_1716CHANGEDfix(gsc): name a malformed sitemap instead of relaying Google's 400 as 502
The
vectraseo-prod-api-gateway-5xxalarm at 2026-10-02 17:27Z was one request:POST /projects/proj_23c433aa19484c6e/gsc/sitemapreturned 502 (integration status 200, 0 t...
- PR_1713CHANGEDfeat: alert owners to misconfigured site URLs
On 2026-10-02 the PipelineWorker logged
sitemap_fetch_errorfor a project whose sitemap URL was saved ashttps:/uibin.orqan.xyz/sitemap.xml(one slash). Every run failed to... - PR_1710CHANGEDfeat(projects): add a refresh button to the Projects page
Adds a refresh button to the
/projectsheader, just left of New Project. Spec:docs/prd/projects-refresh-button.md, produced by spec-clarifier and passing its strict check. - PR_1708CHANGEDfix(truth): let automatic recovery re-check unconfirmed capabilities from surplus
post_34d7c1a4cd114be1(Folio, "email cost calculator for multiple domains") stayed inreview_requiredwith 1 claim unconfirmed: *"The FolioInbox Studio plan accommodates up... - PR_1706CHANGEDCut repair-loop waste and make Gemini spend measurable per model and task
After 2026-09-23, Gemini spend per post went from about $0.18 to $0.76. DeepSeek only takes about $0.03 off each post. This week 61% of model calls went to the repair ladder, an...
- PR_1704CHANGEDfix(claims): a learned row's preferred wording follows the live contract
learned_publish_constraintsrows copypreferred_wordingfrom the rejection that created them, and nothing ever refreshes it. When a destination's product changes, the row ke...