From 404a88aeb8349761c716981ca3f33c8bcc94f843 Mon Sep 17 00:00:00 2001 From: DroidAgent <154886644+echobt@users.noreply.github.com> Date: Tue, 15 Sep 2026 09:00:17 +0000 Subject: [PATCH 1/4] docs: prod FernDesk IA refactor (no public staging) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure the public site around the products that actually exist, remove every staging entry point, and make FernDesk sync production-only. Public IA - docs.json: Get started | Chat | Code | Bot | CLI | API | Changelog, with Get started -> Build by product -> API reference -> Operate mirroring a platform docs site. Home rewritten in that order, replacing the help-center "How can we help" landing. - Design is gone as a product vertical: pages, tab, footer entry, home card, banner, and the five links pointing at it. Its one durable idea — a document panel beside a conversation — is Chat's canvas and stays documented there. - Folded duplicate hubs into their product pages (chat/code/bot/design overview -> index, chat/streaming -> chat/how-it-works, code/cli -> CLI, platform -> api/overview, getting-started/desktop -> downloads). 87 pages, 87 nav entries, no orphans, with redirects for every removed path. Staging - Removed the staging mirror: no staging pages, nav, redirects, or copy. The sync refuses any FERNDESK_TARGET but production, the workflow no longer offers a staging choice, and check-docs-site now fails on staging in navigation, redirects, or page copy. FernDesk sync correctness - Article identity is now the Mintlify `path:` marker, not the slug. FernDesk rewrites a taken slug (`chat` -> `chat-8hul5`), so resolving by slug made a cache-losing run miss its article and create another copy — the cause of the live site's nine `index-*` articles and duplicate hubs. The scan indexes by path, reports duplicates, and the cache carries the path index. - FERNDESK_RETIRE=1 unpublishes duplicates and articles whose page is gone, keeping the canonical article and never touching a hand-written one. Also: AGENTS.md rewritten as the source of truth for this tree, README and scripts/FERNDESK.md updated for FernDesk, and the retired fake-UI SVG plates plus their generator deleted. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> --- scripts/check-docs-site.mjs | 42 +++++++++++++++ scripts/tests/check-docs-site.test.sh | 74 +++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/scripts/check-docs-site.mjs b/scripts/check-docs-site.mjs index f7447c2..98fc2a8 100644 --- a/scripts/check-docs-site.mjs +++ b/scripts/check-docs-site.mjs @@ -210,6 +210,46 @@ const AUTH_INTERNALS = [ { pattern: /client_secret/i, label: 'client secret' }, ]; +/** + * Staging must never reach the public site again. + * + * `docs.cortex.foundation` is the public Mintlify site, and it once publicly + * served `/staging/*` pages plus a Staging collection. Deleting those files is + * not enough: a re-added `staging/…` page, a nav entry, or a redirect into one + * would put pre-prod copy back on the public domain. This holds the line + * mechanically, the same way the auth-internal check does. + */ +function assertNoStagingNav(docsJson) { + let parsed; + try { + parsed = JSON.parse(docsJson); + } catch { + return; // already reported as invalid JSON + } + const seen = new Set(); + for (const slug of navPages(parsed)) { + if (!/(^|\/)staging(\/|$)/i.test(slug) || seen.has(slug)) continue; + seen.add(slug); + fail(`docs.json navigation must not publish a staging page (${slug})`); + } + const redirectSources = Array.isArray(parsed.redirects) ? parsed.redirects : []; + for (const rule of redirectSources) { + if (typeof rule?.destination === 'string' && /(^|\/)staging(\/|$)/i.test(rule.destination)) { + fail(`docs.json redirect ${rule.source} points at a staging page`); + } + } +} + +function assertNoStagingContent(rel, text) { + if (!rel.endsWith('.mdx')) return; + if (/\/staging(\/|$)/.test(text)) { + fail(`${rel} links to a staging path (public docs have no staging mirror)`); + } + if (/\bstaging\b/i.test(text) && !/no staging|not staging|retired/i.test(text)) { + fail(`${rel} tells readers about staging (public docs are production only)`); + } +} + function assertNoAuthInternals(rel, text) { if (!rel.endsWith('.mdx')) return; for (const { pattern, label } of AUTH_INTERNALS) { @@ -321,6 +361,7 @@ if (!existsSync(join(docsRoot, 'docs.json'))) { fail('docs.json still names docs.cortex.sh'); } assertDocsChrome(docsJson); + assertNoStagingNav(docsJson); } for (const rel of FORBIDDEN_AUTH_PAGES) { @@ -363,6 +404,7 @@ for (const file of docsFiles) { ); } assertNoAuthInternals(rel, text); + assertNoStagingContent(rel, text); if (BACKEND === null) continue; for (const path of documentedV1Paths(text)) { const norm = normalizePath(path); diff --git a/scripts/tests/check-docs-site.test.sh b/scripts/tests/check-docs-site.test.sh index e3de33d..5632fe8 100755 --- a/scripts/tests/check-docs-site.test.sh +++ b/scripts/tests/check-docs-site.test.sh @@ -362,4 +362,78 @@ cat > "$missinghref/site/docs.json" <<'JSON' JSON must_fail "$missinghref" "missing-mintlify-page" +# Staging must not return to the public site. docs.cortex.foundation served a +# /staging collection publicly once; a re-added page, nav entry, or redirect +# would put pre-prod copy back on the domain. +stagingnav="$tmp/staging-nav" +seed "$stagingnav" +mkdir -p "$stagingnav/site/staging" +cat > "$stagingnav/site/staging/index.mdx" <<'MDX' +--- +title: "Index" +--- +Staging mirror — unpublished drafts / pre-prod docs +MDX +cat > "$stagingnav/site/docs.json" <<'JSON' +{ + "name": "Cortex", + "logo": { "href": "https://docs.cortex.foundation" }, + "navbar": { + "links": [ + { "label": "Home", "href": "/" }, + { "label": "Documentation", "href": "/problems/not_found" } + ] + }, + "navigation": { + "tabs": [ + { + "tab": "Staging", + "groups": [ + { "group": "Drafts", "pages": ["staging/index"] } + ] + } + ] + } +} +JSON +must_fail "$stagingnav" "staging" + +# A redirect into a staging path is the same leak by another route. +stagingredirect="$tmp/staging-redirect" +seed "$stagingredirect" +cat > "$stagingredirect/site/docs.json" <<'JSON' +{ + "name": "Cortex", + "logo": { "href": "https://docs.cortex.foundation" }, + "navbar": { + "links": [ + { "label": "Home", "href": "/" }, + { "label": "Documentation", "href": "/problems/not_found" } + ] + }, + "redirects": [ + { "source": "/drafts", "destination": "/staging/index" } + ], + "navigation": { + "tabs": [ + { + "tab": "API", + "groups": [ + { "group": "Problems", "pages": ["problems/not_found", "problems/internal"] } + ] + } + ] + } +} +JSON +must_fail "$stagingredirect" "staging" + +# Copy that sends a reader to a staging host or path must fail even when the +# page itself is fine. +stagingcopy="$tmp/staging-copy" +seed "$stagingcopy" +printf '\nUse the staging environment at `/staging/api` for pre-prod keys.\n' \ + >> "$stagingcopy/site/problems/not_found.mdx" +must_fail "$stagingcopy" "staging" + echo "check-docs-site: ok" From 4dcfb62520fb4bfa0511fe62289a636c77acb118 Mon Sep 17 00:00:00 2001 From: DroidAgent <154886644+echobt@users.noreply.github.com> Date: Tue, 15 Sep 2026 09:16:48 +0000 Subject: [PATCH 2/4] docs: drop the "Designer" name from the CLI runtime pack "Designer" was the upstream renderer's name for the pack, but it reads as the retired Design product on a site where Design is not a vertical. Name the pack for what it is. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> --- changelog.mdx | 2 +- images/cli/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog.mdx b/changelog.mdx index a47438a..8bc1732 100644 --- a/changelog.mdx +++ b/changelog.mdx @@ -14,7 +14,7 @@ Dated notes on what the products ship. Each entry names a change the app or the - **`/goal`** — persisted long-horizon objectives with `goal.json` on the session, an 8-turn budget, evidence-based completion, and a composer chip — merged to the CLI main branch in [CortexLM/cli #54](https://github.com/CortexLM/cli/pull/54). It ships with the next tagged release; `cortex upgrade` will pick it up. See [Goals](/cli/goal). - **One approval path** — the permission prompt is the locked inline numbered picker (run once · always allow in this project · edit command · decline), merged in [#53](https://github.com/CortexLM/cli/pull/53). See [Modes and permissions](/cli/modes-and-permissions). -- The Designer runtime pack — headless renders of every TUI state at 120×40 — is what the [CLI pages](/cli) now show. The README demo on a green macOS desktop is regenerated from the same chrome. +- The CLI runtime pack — headless renders of every TUI state at 120×40 — is what the [CLI pages](/cli) now show. The README demo on a green macOS desktop is regenerated from the same chrome. - Release: [v0.1.10 on GitHub](https://github.com/CortexLM/cli/releases/tag/v0.1.10). Update with `cortex upgrade`. diff --git a/images/cli/README.md b/images/cli/README.md index 1d167e9..edb8c20 100644 --- a/images/cli/README.md +++ b/images/cli/README.md @@ -9,7 +9,7 @@ exactly one page; no two files share a sha256. `docs/media/intro.gif` — the README demo: the signed lock TUI composited onto a photographed macOS desktop. Generated, not a live recording. Used on `cli/index`. -## `runtime/` — Designer cli pack +## `runtime/` — CLI runtime pack Headless `MockTerminal` renders of the live session chrome, vendored byte-for-byte from CortexLM/cli tip `4d41ef362481ec816ac395e0e64fe6a54327de14` From 3ad11f81bbdeae806260ec28613519456029d1f3 Mon Sep 17 00:00:00 2001 From: DroidAgent <154886644+echobt@users.noreply.github.com> Date: Tue, 15 Sep 2026 09:24:13 +0000 Subject: [PATCH 3/4] docs: guard against orphaned pages and catalog drift Two drift classes this refactor fixed by hand are now checked, so the next change cannot quietly reintroduce them. - **Orphaned pages.** An MDX page no navigation entry reaches still syncs to FernDesk and still gets indexed, but no reader can navigate to it. That is how the tree grew a second hub for every product (`chat/overview` beside `chat/index`). CI now fails on any page the sidebar cannot reach. - **Catalog drift.** `problems/index.mdx` is hand-maintained while the pages beside it are generated in lockstep with the backend. CI now checks both directions: every problem page is linked from the index, and every link has a page. Both are covered by new cases in check-docs-site.test.sh (orphan, catalog missing a page, catalog linking a ghost code). Content pass alongside it: - The CLI hub's card grid duplicated the sidebar entry for entry. It now keeps a curated set of six cards and lists the rest in a table, so the page adds orientation instead of repeating navigation. - `getting-started/settings` and `security/overview` carried near-identical Data & privacy tables. Settings now says where each control lives; Security stays the canonical account of what each one stores and means. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> --- cli/index.mdx | 35 ++++++--------- getting-started/settings.mdx | 21 ++++----- scripts/check-docs-site.mjs | 61 +++++++++++++++++++++++++++ scripts/tests/check-docs-site.test.sh | 60 +++++++++++++++++++++++++- security/overview.mdx | 3 ++ 5 files changed, 147 insertions(+), 33 deletions(-) diff --git a/cli/index.mdx b/cli/index.mdx index bcca9c0..b5091a6 100644 --- a/cli/index.mdx +++ b/cli/index.mdx @@ -58,24 +58,6 @@ cortex First session, `AGENTS.md`, choosing autonomy. - - Timeline rows, the composer, status line, queueing follow-ups, interrupting. - - - Everything after `/` — model, mode, permissions, plan, goal, sessions, MCP, diagnostics. - - - Agent / Plan / Ask, Spec, approvals, sandbox, the `permission` table, effort. - - - `/goal` — a persisted long-horizon objective that survives compaction and resume. - - - Resume, rewind, fork, export, import, share, lock, clean up. - - - Every binding, grouped by where it applies — plus the Ctrl+X overlay. - `cortex exec` and `cortex run` in scripts, GitHub Actions, GitLab CI. @@ -85,11 +67,22 @@ cortex MCP servers, skills, agents and subagents, hooks, plugins, themes. - - Outage copy, hosts that refuse, the agent that will not edit, MCP, quotas. - +## In the terminal + +The rest of the CLI reference lives in the sidebar under this tab: + +| Page | What it covers | +| --- | --- | +| [The TUI](/cli/tui) | Timeline rows, the composer, status line, queueing follow-ups, interrupting | +| [Slash commands](/cli/slash-commands) | Everything after `/` — model, mode, permissions, plan, goal, sessions, MCP, diagnostics | +| [Modes and permissions](/cli/modes-and-permissions) | Agent / Plan / Ask, Spec, approvals, sandbox, the `permission` table, effort | +| [Goals](/cli/goal) | `/goal` — a persisted long-horizon objective that survives compaction and resume | +| [Sessions](/cli/sessions) | Resume, rewind, fork, export, import, share, lock, clean up | +| [Keyboard shortcuts](/cli/keyboard) | Every binding, grouped by where it applies — plus the Ctrl+X overlay | +| [CLI troubleshooting](/cli/troubleshooting) | Outage copy, hosts that refuse, the agent that will not edit, MCP, quotas | + ## Conventions on these pages - Commands are written `cortex …`. The installed binary is `Cortex`; the installer adds `cortex` and `agent` symlinks, and both spellings work on case-insensitive filesystems. diff --git a/getting-started/settings.mdx b/getting-started/settings.mdx index 00ec2e8..1dbcc0a 100644 --- a/getting-started/settings.mdx +++ b/getting-started/settings.mdx @@ -59,17 +59,18 @@ Model availability depends on your plan. During peak hours new chats may fall ba ## Data & privacy -| Control | Default | Notes | +Where each control lives. What each one stores, and what it means, is on +[Security and privacy](/security/overview). + +| Control | Where | Notes | | --- | --- | --- | -| **Save chat history** | On | Conversations are kept in your account so you can pick them up on any device. *Coming soon* as a toggle. | -| **Improve the model** | Off | When on, a sample of your conversations may be reviewed to train future models. Your chats are never used without this setting. *Coming soon.* | -| **Necessary cookies** | Always on | Session, language, and this preference. Cortex cannot work without them. | -| **Optional analytics** | Off | Stays off until you allow it. Nothing in the current build loads an optional tracker. | -| **Memory** | — | Review or delete individual memories. See [Memory](/chat/memory). | -| **Two-factor authentication** | — | A signed-in account uses an authenticator app to confirm export and deletion. | -| **Your data** | — | **Export my data** and **Delete all data**. Deletion takes effect within 30 days. | - -See [Security](/security/overview) for what Cortex stores and where code runs. +| **Save chat history** | Data & privacy | On by default. *Coming soon* as a toggle. | +| **Improve the model** | Data & privacy | Off by default. Your chats are never used without this setting. *Coming soon.* | +| **Necessary cookies** | Data & privacy | Session, language, and this preference. Cortex cannot work without them. | +| **Optional analytics** | Data & privacy | Stays off until you allow it. Nothing in the current build loads an optional tracker. | +| **Memory** | Data & privacy | Review or delete individual memories. See [Memory](/chat/memory). | +| **Two-factor authentication** | Data & privacy | An authenticator app confirms export and deletion. | +| **Export my data / Delete all data** | Data & privacy | Deletion takes effect within 30 days. | ## Plan & billing diff --git a/scripts/check-docs-site.mjs b/scripts/check-docs-site.mjs index 98fc2a8..6345605 100644 --- a/scripts/check-docs-site.mjs +++ b/scripts/check-docs-site.mjs @@ -201,6 +201,35 @@ function assertNavPagesExist(parsed) { } } +/** + * An MDX page no navigation entry reaches is dead weight: it still gets + * indexed, and still shows up in search — but no reader can navigate to it. + * This is how the old tree accumulated a second hub for every product + * (`chat/overview` beside `chat/index`) and pages whose only inbound links + * were from other orphans. + * + * The home page is reachable from the navbar's `/` link, which `pushNavSlug` + * drops as a non-slug, so it is exempted by name. + */ +function assertNoOrphanPages(docsJson) { + let parsed; + try { + parsed = JSON.parse(docsJson); + } catch { + return; // already reported as invalid JSON + } + const nav = new Set(navPages(parsed)); + for (const file of walk(ROOT)) { + if (!file.endsWith('.mdx')) continue; + const slug = relative(ROOT, file).replace(/\.mdx$/, ''); + if (slug === 'index') continue; + if (nav.has(slug) || nav.has(slug.replace(/\/index$/, ''))) continue; + fail( + `${slug}.mdx is not reachable from docs.json navigation (orphaned page)`, + ); + } +} + const AUTH_INTERNALS = [ { pattern: /\/auth\//, label: '/auth/' }, { pattern: /\/oauth\//, label: '/oauth/' }, @@ -350,6 +379,37 @@ for (const extra of pageCodes) { } } +/** + * The catalog table in `problems/index.mdx` is hand-maintained while the pages + * beside it are generated in lockstep with the backend. That is the same decay + * this file exists to catch: a new code lands as a page, the catalog keeps + * listing the old set, and the index — the page a reader actually lands on — + * silently stops being complete. + */ +function assertCatalogCoversPages() { + const rel = 'problems/index.mdx'; + if (!existsSync(join(ROOT, rel))) { + fail(`${rel} is missing (problem catalog index)`); + return; + } + const catalog = read(rel); + const listed = new Set( + [...catalog.matchAll(/\]\(\/problems\/([a-z_]+)\)/g)].map((m) => m[1]), + ); + for (const code of pageCodes) { + if (!listed.has(code)) { + fail(`${rel} does not link \`${code}\`; every problem page belongs in the catalog`); + } + } + for (const code of listed) { + if (!pageCodes.has(code)) { + fail(`${rel} links \`${code}\`, which has no page at problems/${code}.mdx`); + } + } +} + +assertCatalogCoversPages(); + if (!existsSync(join(docsRoot, 'docs.json'))) { fail('docs.json is missing (Mintlify site config)'); } else { @@ -362,6 +422,7 @@ if (!existsSync(join(docsRoot, 'docs.json'))) { } assertDocsChrome(docsJson); assertNoStagingNav(docsJson); + assertNoOrphanPages(docsJson); } for (const rel of FORBIDDEN_AUTH_PAGES) { diff --git a/scripts/tests/check-docs-site.test.sh b/scripts/tests/check-docs-site.test.sh index 5632fe8..c6630cb 100755 --- a/scripts/tests/check-docs-site.test.sh +++ b/scripts/tests/check-docs-site.test.sh @@ -58,7 +58,7 @@ RS "groups": [ { "group": "Problems", - "pages": ["problems/not_found", "problems/internal"] + "pages": ["problems/index", "problems/not_found", "problems/internal"] } ] } @@ -79,6 +79,16 @@ title: "${code}" | \`GET\` | \`/v1/conversations\` | MDX done + cat > "$dest/site/problems/index.mdx" <<'MDX' +--- +title: "Problem catalog" +--- + +| Code | HTTP | +| --- | --- | +| [`not_found`](/problems/not_found) | 404 | +| [`internal`](/problems/internal) | 500 | +MDX } must_fail() { @@ -318,7 +328,7 @@ cat > "$goodroot/site/docs.json" <<'JSON' { "group": "Problems", "root": "problems/not_found", - "pages": ["problems/internal"] + "pages": ["problems/internal", "problems/index"] } ] } @@ -436,4 +446,50 @@ printf '\nUse the staging environment at `/staging/api` for pre-prod keys.\n' \ >> "$stagingcopy/site/problems/not_found.mdx" must_fail "$stagingcopy" "staging" +# A page no navigation entry reaches still gets indexed, but no reader can +# navigate to it. That is how the tree accumulated a second hub for every +# product. +orphan="$tmp/orphan-page" +seed "$orphan" +cat > "$orphan/site/problems/leftover.mdx" <<'MDX' +--- +title: "Leftover" +--- + +`type` is `https://docs.cortex.foundation/problems/leftover`. +MDX +must_fail "$orphan" "orphaned page" + +# The catalog index is hand-maintained while the pages beside it are generated +# in lockstep with the backend. A page the catalog forgets is invisible to the +# reader who lands on the index. +drift="$tmp/catalog-drift" +seed "$drift" +cat > "$drift/site/problems/index.mdx" <<'MDX' +--- +title: "Problem catalog" +--- + +| Code | HTTP | +| --- | --- | +| [`not_found`](/problems/not_found) | 404 | +MDX +must_fail "$drift" "does not link \`internal\`" + +# And the reverse: a catalog entry with no page behind it. +dangling="$tmp/catalog-dangling" +seed "$dangling" +cat > "$dangling/site/problems/index.mdx" <<'MDX' +--- +title: "Problem catalog" +--- + +| Code | HTTP | +| --- | --- | +| [`not_found`](/problems/not_found) | 404 | +| [`internal`](/problems/internal) | 500 | +| [`ghost`](/problems/ghost) | 500 | +MDX +must_fail "$dangling" "no page at problems/ghost.mdx" + echo "check-docs-site: ok" diff --git a/security/overview.mdx b/security/overview.mdx index ca25058..340a1cd 100644 --- a/security/overview.mdx +++ b/security/overview.mdx @@ -31,6 +31,9 @@ From **Settings → Data & privacy**, in the product's own words: your account d | **Two-factor authentication** | — | A signed-in account uses an authenticator app to confirm export and deletion. | | **Export my data / Delete all data** | — | Export everything held, or delete it permanently. Deletion takes effect within 30 days. | +These live under **Settings → Data & privacy**; [Settings](/getting-started/settings) +lists where each control is. The table above is what each one stores. + ## Permissions A guest cannot connect a plugin or MCP server, hold a GitHub grant, create a bot, or open Code's working UI. That is fail-closed by design: a guest session cannot be signed back into to revoke a grant later, so it is never allowed to create one. From b55a47f30ad1ebeca291c1ff2c70e2290dc084c6 Mon Sep 17 00:00:00 2001 From: DroidAgent <154886644+echobt@users.noreply.github.com> Date: Tue, 15 Sep 2026 09:29:43 +0000 Subject: [PATCH 4/4] docs: cut repeated copy from quickstart and status - The quickstart listed the four surfaces twice: once as a step, then again as a card grid. The card grid stays, with its descriptions. - System status said "check status.cortex.foundation" three times and closed on a note about brand colours and domain hosting, which is internal reasoning rather than something a reader needs. The page now states what the status site covers and when to use it, once. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> --- getting-started/quickstart.mdx | 9 --------- status.mdx | 14 +++----------- 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/getting-started/quickstart.mdx b/getting-started/quickstart.mdx index 7ee2863..a3fb143 100644 --- a/getting-started/quickstart.mdx +++ b/getting-started/quickstart.mdx @@ -39,15 +39,6 @@ Cortex is one account across four products: **Chat**, **Code**, **Bot**, and **D Choose **Sign in to save your work** in the sidebar footer. A signed-in account keeps chats, projects, Library files, plans, and Bot routines across devices, and unlocks Code and Bot. See [Accounts](/getting-started/accounts). - - | Surface | First useful thing | Guide | - | --- | --- | --- | - | **Chat** | Create a project with standing instructions | [Chat quickstart](/chat/quickstart) | - | **Code** | Connect GitHub and start a Cloud session on a repository | [Code quickstart](/code/quickstart) | - | **Bot** | Create a bot and open its computer | [Bot quickstart](/bot/quickstart) | - | **CLI** | Install, sign in, run `cortex` in a project | [CLI quickstart](/cli/quickstart) | - | **Design** | Host a canvas from Chat or Code, then open it on desktop | [Design](/design) | - ## Install the desktop app or the CLI diff --git a/status.mdx b/status.mdx index b38cc13..fa004fa 100644 --- a/status.mdx +++ b/status.mdx @@ -8,17 +8,13 @@ keywords: ["uptime", "outage", "incident", "maintenance", "availability"] Cortex -Cortex publishes live component health, incident history, and scheduled maintenance on the public status page. +Live component health, incident history, and scheduled maintenance are published on **[status.cortex.foundation](https://status.cortex.foundation)**. Bookmark that page; this article explains what it covers and how it relates to product troubleshooting.

Open status.cortex.foundation Troubleshooting

- -The canonical status URL is **[status.cortex.foundation](https://status.cortex.foundation)**. Bookmark that page for outages and planned maintenance. This docs article explains what it covers and how it relates to product troubleshooting. - - ## What we report | Component | What it covers | @@ -33,8 +29,8 @@ Component names stay product-facing. Individual incidents may mark one or more o ## During an incident -1. Check **[status.cortex.foundation](https://status.cortex.foundation)** for the current banner and component states. -2. Subscribe on that page if you want email (or other) updates for the next change. +1. Check the status page for the current banner and component states. +2. Subscribe there if you want updates for the next change. 3. Keep any `request_id` from an error in the app — see [Troubleshooting](/getting-started/troubleshooting) and the [problem catalog](/problems). User-facing error text names a Cortex surface, never a vendor. Status updates are the place for fleet-wide notices. @@ -48,10 +44,6 @@ User-facing error text names a Cortex surface, never a vendor. Status updates ar | [Security and privacy](/security/overview) | Data handling — not availability | | [Changelog](/changelog) | What shipped — not outages | -## Brand - -Status communications use Cortex green (`#1F4945`) and the Cortex logo. The status site is hosted under the `cortex.foundation` domain so it stays available when you need it most. - ## Related - [Troubleshooting](/getting-started/troubleshooting) — what a message in the product means.