Skip to content

docs: fix sei-skill bridges, add AI menu targets, and check redirects in CI - #84

Merged
alexander-sei merged 10 commits into
mainfrom
docs/menu-targets-and-redirect-check
Sep 30, 2026
Merged

alexander-sei merged 10 commits into
mainfrom
docs/menu-targets-and-redirect-check

Conversation

@alexander-sei

Copy link
Copy Markdown
Collaborator

What is the purpose of the change?

Corrects stale content on the sei-skill overview, adds three AI targets to the page menu, removes two redirects that never fire, and adds a CI guard so redirects can't silently point at missing pages. These are the quick wins from the Sei vs. Solana docs review.

Describe the changes to the documentation

  • ai/sei-skill/index.mdx: The bridges line listed Wormhole and Axelar. It now matches the current skill source (sei-skill@e2445c8): LayerZero V2 and Circle CCTP v2 are the bridges Sei documents, and IBC is disabled in both directions, linked to the SIP-03 section that explains it.
  • Page menu (docs.json → contextual.options): Adds grok, aistudio, and add-mcp. All three are in the enum in Mintlify's published docs.json schema. assistant, devin, and devin-mcp are also available but left out for now; assistant responses cost Mintlify credits.
  • Redirects (docs.json): Removes /evm/MyContract.json and /genesis.json. I requested all 239 redirect sources on docs.sei.io: 237 land on their destination, and these two return 404 without redirecting. Mintlify doesn't apply redirects to paths ending in .json.
  • CI (validate-docs.yml, scripts/check-redirects.mjs): A new step fails when a redirect's destination isn't a page in the repo (or, for :slug* destinations, a directory to forward into). It also flags a destination that is itself a redirect. AGENTS.md now mentions the script in its Redirects section.

Notes

  • Verified locally: node scripts/check-redirects.mjs passes for all 237 destinations. Injected bad redirects (missing page, missing wildcard directory, redirect chain, wrong-case path) each fail, and anchors, query strings, external URLs, and / pass. mint validate (strict) and mint broken-links pass with the latest CLI, typos passes, and Vale reports nothing on the changed lines.
  • The sei-skill repo's own README still lists Axelar under bridges, which contradicts its references/ecosystem/bridges.md. That fix belongs in sei-protocol/sei-skill.

alexander-sei and others added 4 commits September 30, 2026 14:05
The overview still listed Wormhole and Axelar as bridges. The skill itself
(sei-protocol/sei-skill@e2445c8) now names LayerZero V2 and Circle CCTP v2
as the bridges Sei documents, treats Wormhole as unverified because Sei has
no Wormhole guide, and no longer mentions Axelar. Say the same here, and
note that IBC is disabled in both directions, linking the SIP-03 section
that explains it.

Co-authored-by: Cursor <cursoragent@cursor.com>
Mintlify's contextual menu supports these targets now. grok and aistudio
sit with the other open-in-chat options; add-mcp copies the npx add-mcp
install command for the hosted MCP server and sits next to the existing
mcp option. The other new targets (assistant, devin, devin-mcp) are left
for a separate decision, since assistant responses cost Mintlify credits.

Co-authored-by: Cursor <cursoragent@cursor.com>
Requesting every redirect source on docs.sei.io, 237 of 239 land on their
destination. /evm/MyContract.json and /genesis.json return 404 without
redirecting, so Mintlify doesn't apply redirects to paths ending in .json
(other extensions, such as /node/priv_validator_state.json.tmp, redirect
fine). Both are artifact paths from the Nextra-era tutorials rather than
pages, so remove entries that never run.

Co-authored-by: Cursor <cursoragent@cursor.com>
validate-docs checks that every nav page exists, but nothing checked
redirect destinations, so renaming or deleting a page could leave redirects
pointing at a 404. scripts/check-redirects.mjs resolves each internal
destination to a page (.mdx, .md, or an index page), a static file such as
/skill.md, or, for :slug* destinations, the directory the match forwards
into. A destination that is itself a redirect source fails with a hint to
point at the final page. Names are compared against directory listings so
the check stays case-sensitive on macOS, matching the Linux runner.

All 237 current destinations pass. Injecting a missing page, a missing
wildcard directory, a redirect chain, and a wrong-case path failed on each;
anchors, query strings, external URLs, and / pass.

Co-authored-by: Cursor <cursoragent@cursor.com>
@mintlify

mintlify Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
sei-docs 🟢 Ready View Preview Sep 30, 2026, 12:55 PM

💡 Tip: Enable Automations to automatically generate PRs for you.

@cursor

cursor Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

PR Summary

Low Risk
Documentation, redirect config, and additive CI validation only; no runtime or security-sensitive code paths.

Overview
Adds CI enforcement so docs.json redirects must resolve to real pages: new scripts/check-redirects.mjs (case-sensitive path checks, wildcard prefix validation, redirect-chain detection) runs in validate-docs.yml, and AGENTS.md tells contributors to run it locally.

Content/config tweaks: ai/sei-skill/index.mdx now documents LayerZero V2 and Circle CCTP v2 for bridges, notes IBC is disabled with a link to SIP-03, and drops outdated Wormhole/Axelar wording. Mintlify contextual menu gains grok, aistudio, and add-mcp. Two non-functional redirects (/evm/MyContract.json, /genesis.json) are removed because Mintlify does not redirect .json paths.

Reviewed by Cursor Bugbot for commit 483f84b. Bugbot is set up for automated code reviews on this repo. Configure here.

@seidroid seidroid Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a small, well-scoped PR: it corrects the sei-skill bridges line, adds three menu targets that are in the schema, removes two redirects that never fire, and adds a sound CI check for redirect destinations. I found no blocking issues; only minor nits remain.

Findings: 0 blocking | 6 non-blocking | 3 posted inline

Blockers

  • None at the file/PR level.

Non-blocking

  • The Cursor review (cursor-review.md) was empty, so that pass produced no output. Codex found no material issues, and I agree.
  • REVIEW_GUIDELINES.md is empty on the base branch, so this review applies only the conventions in AGENTS.md.
  • I confirmed that the new link anchor /learn/sip-03-migration#ibc-is-disabled matches the ## IBC is disabled heading on that page. The CI job runs on ubuntu-latest, and its Node version supports top-level await, so the new step needs no setup-node change.
  • 3 suggestion(s)/nit(s) flagged inline on specific lines.

Comment thread ai/sei-skill/index.mdx Outdated
**Ecosystem** — infrastructure and integrations:
- RPC endpoints (public, community, paid SaaS)
- Bridges (LayerZero V2, Wormhole, Axelar, CCTP)
- Bridges (LayerZero V2, Circle CCTP v2 for native USDC); IBC is [disabled in both directions](/learn/sip-03-migration#ibc-is-disabled)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] This bullet puts two ideas into one line joined by a semicolon: the supported bridges and the IBC status. AGENTS.md prefers one idea per sentence. Consider moving the IBC note into its own bullet, for example - IBC is [disabled in both directions](...).


const candidates = path
? [path, `${path}.mdx`, `${path}.md`, `${path}/index.mdx`, `${path}/index.md`]
: ['index.mdx', 'index.md'];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] The first candidate is the bare path, so any file in the repo counts as a valid destination, including docs.json, images, and scripts. Pages are .mdx/.md, so this can hide a typo'd destination that happens to match a non-page file. It's fine if static-asset destinations are intended; otherwise consider dropping the bare-path candidate or limiting it to known asset extensions.

Comment thread scripts/check-redirects.mjs Outdated
const target = `/${path}`;
failures.push(
sources.has(target)
? `${source} -> ${destination}: ${target} is itself a redirect; point at its destination instead`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] The redirect-chain check only runs when no page exists at the destination. A destination that is both a page and a redirect source is never flagged. That's probably harmless, but the PR description says the script flags any destination that is itself a redirect, which is broader than what the code does. Consider narrowing the description or checking sources.has(target) without the page condition.

alexander-sei and others added 2 commits September 30, 2026 14:13
The bridges bullet carried two ideas joined by a semicolon, and AGENTS.md
asks for one idea per sentence (seidroid nit on #84).

Co-authored-by: Cursor <cursoragent@cursor.com>
Two seidroid nits on #84. The chain check only ran when no page existed at
the destination, so a destination that was both a page and a redirect
source passed; check sources first so any chained destination fails. And
any repo file counted as a destination, so a typo matching docs.json, a
script, or an image would pass; only markdown and text files such as
/skill.md and /llms.txt can now match directly.

All 237 current destinations still pass. /docs.json, /favicon.svg, and a
destination that is both a page and a redirect source now fail alongside
the earlier missing-page, wildcard, chain, and wrong-case cases.

Co-authored-by: Cursor <cursoragent@cursor.com>

@seidroid seidroid Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a small, well-scoped PR. It corrects the sei-skill bridges list, adds three valid page-menu AI targets, drops two .json redirects that never fire, and adds a CI check that redirect destinations exist. The new #ibc-is-disabled anchor resolves in learn/sip-03-migration.mdx, and Codex reports that the checker passes. I found nothing blocking, only minor notes.

Findings: 0 blocking | 5 non-blocking | 2 posted inline

Blockers

  • None at the file/PR level.

Non-blocking

  • The Cursor second-opinion review file (cursor-review.md) was empty, so that pass produced no output. REVIEW_GUIDELINES.md was also empty, so I used AGENTS.md conventions instead.
  • check-redirects.mjs only flags a redirect chain when the destination exactly matches a static source. A destination that is caught by a wildcard source such as /.sei/:path* would not be flagged. This is acceptable for now, but worth knowing about.
  • The checker only verifies that a page file exists. It does not check that the destination is listed in docs.json navigation. An orphaned page would pass, although the existing orphaned-MDX step partly covers this.
  • 2 suggestion(s)/nit(s) flagged inline on specific lines.

Comment thread ai/sei-skill/index.mdx Outdated
- RPC endpoints (public, community, paid SaaS)
- Bridges (LayerZero V2, Wormhole, Axelar, CCTP)
- Bridges (LayerZero V2, Circle CCTP v2 for native USDC)
- IBC is [disabled in both directions](/learn/sip-03-migration#ibc-is-disabled)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] The IBC line isn't an integration, so it reads a little oddly in a list of infrastructure items. Consider folding it into the bridges bullet, for example: Bridges (LayerZero V2, Circle CCTP v2 for native USDC; IBC is [disabled in both directions](...)).

Comment thread scripts/check-redirects.mjs Outdated
// script, or an image.
const candidates = path
? [
...(/\.(md|txt)$/.test(path) ? [path] : []),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] The elements of the array inside the ternary are indented at the same level as the ? [. Indenting them one more level, or letting Prettier format the block, would read more clearly.

The multi-line array inside the ternary was indented at the same level as
its bracket (seidroid nit on #84). Keep the page candidates on one line and
push the direct-file candidate separately. Behavior is unchanged: the same
237 destinations pass and the same injected cases fail.

Co-authored-by: Cursor <cursoragent@cursor.com>

@seidroid seidroid Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a clean, well-scoped PR. It corrects the sei-skill bridges list, adds valid AI menu targets, drops two .json redirects that never fire, and adds a sound CI check for redirect destinations. I found no blocking issues, only minor notes.

Findings: 0 blocking | 5 non-blocking | 1 posted inline

Blockers

  • None at the file/PR level.

Non-blocking

  • The Cursor review file (cursor-review.md) was empty, so that pass produced no output. Codex reported no material issues, and the redirect checker passed for all 237 local destinations.
  • REVIEW_GUIDELINES.md is empty, so I applied only the conventions in AGENTS.md.
  • The redirect-chain check in scripts/check-redirects.mjs compares exact strings only. It misses a destination that differs from a redirect source by a trailing slash, and one that a wildcard source (for example /.sei/:path*) would match. This is acceptable for now; consider normalizing trailing slashes if chains become a concern.
  • I verified that the #ibc-is-disabled anchor exists in learn/sip-03-migration.mdx (the ## IBC is disabled heading).
  • 1 suggestion(s)/nit(s) flagged inline on specific lines.

Comment thread ai/sei-skill/index.mdx Outdated
- RPC endpoints (public, community, paid SaaS)
- Bridges (LayerZero V2, Wormhole, Axelar, CCTP)
- Bridges (LayerZero V2, Circle CCTP v2 for native USDC)
- IBC is [disabled in both directions](/learn/sip-03-migration#ibc-is-disabled)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] This IBC note sits in the Ecosystem list as its own bullet, but it isn't an infrastructure item like the others. Consider folding it into the Bridges bullet. For example: Bridges (LayerZero V2, Circle CCTP v2 for native USDC; IBC is [disabled in both directions](...)). Or nest it under Bridges as a sub-bullet.

alexander-sei and others added 2 commits September 30, 2026 14:50
seidroid asked on #84 first for the IBC note to be its own line (one idea
per sentence), then pointed out that a top-level IBC bullet isn't an
infrastructure item like its neighbors. A sub-bullet under Bridges keeps
both: its own line, grouped with the bridges it constrains.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ions

Destinations were already compared without a trailing slash, but sources
were compared as written, so a source like /evm/networks/ never matched a
destination of /evm/networks and the chain went unflagged (seidroid note
on #84). Strip trailing slashes from sources too, keeping / as the root.

All 237 current destinations still pass, and an injected /evm/networks/
source now fails the redirect that points at /evm/networks.

Co-authored-by: Cursor <cursoragent@cursor.com>

@seidroid seidroid Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The content fix, the page-menu additions, the removal of two dead .json redirects, and the new redirect-destination check in CI all look correct. The #ibc-is-disabled anchor exists in learn/sip-03-migration.mdx, and Codex found no issues. Only minor notes remain.

Findings: 0 blocking | 5 non-blocking | 2 posted inline

Blockers

  • None at the file/PR level.

Non-blocking

  • The Cursor review file (cursor-review.md) was empty, so that pass produced no output. REVIEW_GUIDELINES.md was also empty, so no repo-specific guidelines were applied.
  • The redirect-chain check only catches exact matches against static sources. A destination covered by a wildcard source (e.g. anything under /.sei/:path*) would still pass as long as a page exists there. This is an acceptable edge case, and a comment in the script could note it.
  • In exists(), the parallel Promise.all(candidates.map(isFile)) calls can race and read the same directory more than once before the cache fills. The result is still correct; it just repeats some work. Caching the readdir promise instead of the resolved Set would remove the duplicate reads.
  • 2 suggestion(s)/nit(s) flagged inline on specific lines.

Comment thread ai/sei-skill/index.mdx
- RPC endpoints (public, community, paid SaaS)
- Bridges (LayerZero V2, Wormhole, Axelar, CCTP)
- Bridges (LayerZero V2, Circle CCTP v2 for native USDC)
- IBC is [disabled in both directions](/learn/sip-03-migration#ibc-is-disabled)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] Nesting the IBC note under "Bridges" reads as if IBC were one of the bridges the skill covers. You could make it a parenthetical on the bridges line, or a separate bullet. Optional.

for (const name of path.split('/')) {
if (!listings.has(dir)) {
listings.set(dir, new Set(await readdir(`${repoDir}${dir}`).catch(() => [])));
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] Suggestion: store the readdir promise in listings, e.g. listings.set(dir, readdir(...).then(n => new Set(n), () => new Set())), and await it. Concurrent isFile calls from Promise.all would then share a single read.

The listing cache stored the resolved Set, so the parallel isFile calls for
one destination could each read the same directory before the cache
filled. Cache the readdir promise instead so they share one read. Also note
in the chain check that only exact sources are matched: a destination under
a wildcard source such as /.sei/:path* is not flagged (both seidroid notes
on #84).

Results are unchanged: all 237 destinations pass and every injected case
still fails.

Co-authored-by: Cursor <cursoragent@cursor.com>

@seidroid seidroid Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is clean and ready to merge. It corrects the bridges list on the sei-skill page and links it to an anchor that exists (#ibc-is-disabled in learn/sip-03-migration.mdx). It adds valid contextual.options entries, removes two .json redirects that never fire, and adds a sound redirect-destination check to CI. Codex found no issues, and I found no blockers.

Findings: 0 blocking | 5 non-blocking | 1 posted inline

Blockers

  • None at the file/PR level.

Non-blocking

  • The Cursor review file (cursor-review.md) was empty, so there was no second opinion from Cursor. Codex reported no material issues and said the redirect check passes for all 237 local destinations.
  • REVIEW_GUIDELINES.md is empty on the base branch, so I reviewed against AGENTS.md conventions only.
  • The chain check in check-redirects.mjs only compares destinations against exact redirect sources. A destination caught by a wildcard source (for example /.sei/:path*) won't be flagged as a chain. The code comment says this is intentional; a regression fixture could be added later if you want to lock in this behavior.
  • Optional: have the script say which case it hit (missing .mdx, missing index, wrong case) so failures are quicker to fix. It's usable as it is.
  • 1 suggestion(s)/nit(s) flagged inline on specific lines.

const isFile = async (path) =>
(await exists(path)) && (await stat(`${repoDir}${path}`)).isFile();
const isDirectory = async (path) =>
!path || ((await exists(path)) && (await stat(`${repoDir}${path}`)).isDirectory());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] isDirectory('') returns true because of the !path || short-circuit. A dynamic destination like /:slug* (no static prefix) therefore always passes. That's reasonable because the repo root always exists, but a short comment would make it clear this is intended.

@alexander-sei
alexander-sei merged commit b8f23a2 into main Sep 30, 2026
17 checks passed
@alexander-sei
alexander-sei deleted the docs/menu-targets-and-redirect-check branch September 30, 2026 13:19

This branch was successfully deployed

1 active deployment
staging — 483f84be Deployed Sep 30, 2026 by mintlify[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant