Eighteen hand-authored pages are in config/navigation.json and have zero inbound internal links from anywhere in the repo. They are reachable only by someone already scrolling the correct sidebar group, so neither a reader following a topic nor Mintlify search ranking can find them from the page where the question arises.
This is cross-reference rot — scripts/audit_navigation.py does not check it, because it only sees the navigation tree, not prose links.
The 18 pages
| Page |
The page a reader is on when they want it |
tutorials/working_with_controls |
understand_kosli/controls, getting_started/enforce_policies |
tutorials/report_gke_envs |
getting_started/environments:61-63 |
tutorials/attest_snyk |
getting_started/attestations |
tutorials/repositories |
getting_started/artifacts, understand_kosli/how_kosli_works |
tutorials/trail_summaries_in_ci |
getting_started/trails, integrations/ci_cd |
tutorials/linking_trails_across_branches |
getting_started/trails |
tutorials/cli_and_http_proxy |
getting_started/install, faq/faq |
administration/managing_environments/overview |
getting_started/environments |
administration/managing_custom_attestation_types/overview |
getting_started/attestations |
administration/dedicated_instance_parameters |
administration/customer_kms_keys |
integrations/launchdarkly |
integrations/ci_cd, understand_kosli/controls |
user/default_organization |
getting_started/install, user/personal_api_keys |
implementation_guide/phase_2/plan_organizational_structure/naming_conventions/overview |
its own group |
implementation_guide/phase_2/plan_organizational_structure/naming_conventions/flows_and_trails |
its own group |
troubleshooting/docker_api_version_error |
faq/faq |
troubleshooting/github_kosli_api_token |
faq/faq, integrations/kosli_actions |
troubleshooting/whitespace_path |
faq/faq |
troubleshooting/zsh_no_such_user |
getting_started/install |
Three findings that make the pattern concrete
1. The newest page was born orphaned. tutorials/report_gke_envs landed yesterday in #436. getting_started/environments.md:61-63 is the page that lists reporting tutorials, and it still says:
You can follow one of the tutorials below to setup automatic snapshot reporting for your environment:
- [Kubernetes environment reporting](/tutorials/report_k8s_envs)
- [AWS ECS/S3/Lambda environment reporting](/tutorials/report_aws_envs)
- [Cloud Run environment reporting](/tutorials/report_cloud_run_envs)
Its three siblings each have three or more inbound links (getting_started/environments, labs/lab-05-runtime-controls:235, helm/k8s_reporter/karpenter:41, tutorials/repositories:132). Adding the fourth line is a one-line fix, and nothing in CI asked for it.
2. The largest hand-authored page on the site is unreachable by link. tutorials/working_with_controls is 3,286 words (per #396) and nothing links to it — not understand_kosli/controls, not getting_started/enforce_policies, not understand_kosli/risks.
3. Four of the seven troubleshooting pages have no inbound links. The three that do (repo_digest_unavailable, subshell_stderr, what_do_i_do_if_kosli_is_down) are linked from elsewhere; docker_api_version_error, github_kosli_api_token, whitespace_path and zsh_no_such_user are not. A troubleshooting page is the one page type a reader never browses to — they arrive from the page that produced the error.
Similarly, the naming_conventions group has three pages and only attestation_types is linked from anywhere; its overview and flows_and_trails siblings are not.
URL impact
None. No page files move, no navigation entries change, no headings are renamed. This is adding links to prose, so no config/redirects.json entry is needed.
What a fix looks like
Add one contextual link from each page in the right-hand column. Not a "See also" dump — a sentence where the subject actually comes up. The GKE line in getting_started/environments.md is the model: the sibling list already exists, the entry is just missing.
Worth doing alongside #395 rather than after it, since the same pages change hands there.
Evidence
Nav pages, minus generated trees, minus everything that appears as a link target anywhere in the repo:
# all non-generated page paths in navigation
grep -oE '"[a-z0-9_][a-zA-Z0-9_/-]*"' config/navigation.json | tr -d '"' | grep '/' \
| grep -vE '^(client_reference/|helm/|terraform-reference/|github-action-reference/)' | sort -u
# all internal link targets in all content
grep -rhoE '\]\(/[a-zA-Z0-9_/.#-]+|href="/[a-zA-Z0-9_/.#-]+' --include=*.md --include=*.mdx . \
| sed -E 's/^\]\(\///; s/^href="\///; s/#.*//; s|/$||' | sort -u
The difference is the table above. changelog/index and labs/index also appear in the difference and are excluded as false positives — both are linked by their tab path (/changelog, /labs).
Found by the monthly doc-structure audit, step 2 (cross-reference rot).
Eighteen hand-authored pages are in
config/navigation.jsonand have zero inbound internal links from anywhere in the repo. They are reachable only by someone already scrolling the correct sidebar group, so neither a reader following a topic nor Mintlify search ranking can find them from the page where the question arises.This is cross-reference rot —
scripts/audit_navigation.pydoes not check it, because it only sees the navigation tree, not prose links.The 18 pages
tutorials/working_with_controlsunderstand_kosli/controls,getting_started/enforce_policiestutorials/report_gke_envsgetting_started/environments:61-63tutorials/attest_snykgetting_started/attestationstutorials/repositoriesgetting_started/artifacts,understand_kosli/how_kosli_workstutorials/trail_summaries_in_cigetting_started/trails,integrations/ci_cdtutorials/linking_trails_across_branchesgetting_started/trailstutorials/cli_and_http_proxygetting_started/install,faq/faqadministration/managing_environments/overviewgetting_started/environmentsadministration/managing_custom_attestation_types/overviewgetting_started/attestationsadministration/dedicated_instance_parametersadministration/customer_kms_keysintegrations/launchdarklyintegrations/ci_cd,understand_kosli/controlsuser/default_organizationgetting_started/install,user/personal_api_keysimplementation_guide/phase_2/plan_organizational_structure/naming_conventions/overviewimplementation_guide/phase_2/plan_organizational_structure/naming_conventions/flows_and_trailstroubleshooting/docker_api_version_errorfaq/faqtroubleshooting/github_kosli_api_tokenfaq/faq,integrations/kosli_actionstroubleshooting/whitespace_pathfaq/faqtroubleshooting/zsh_no_such_usergetting_started/installThree findings that make the pattern concrete
1. The newest page was born orphaned.
tutorials/report_gke_envslanded yesterday in #436.getting_started/environments.md:61-63is the page that lists reporting tutorials, and it still says:Its three siblings each have three or more inbound links (
getting_started/environments,labs/lab-05-runtime-controls:235,helm/k8s_reporter/karpenter:41,tutorials/repositories:132). Adding the fourth line is a one-line fix, and nothing in CI asked for it.2. The largest hand-authored page on the site is unreachable by link.
tutorials/working_with_controlsis 3,286 words (per #396) and nothing links to it — notunderstand_kosli/controls, notgetting_started/enforce_policies, notunderstand_kosli/risks.3. Four of the seven troubleshooting pages have no inbound links. The three that do (
repo_digest_unavailable,subshell_stderr,what_do_i_do_if_kosli_is_down) are linked from elsewhere;docker_api_version_error,github_kosli_api_token,whitespace_pathandzsh_no_such_userare not. A troubleshooting page is the one page type a reader never browses to — they arrive from the page that produced the error.Similarly, the
naming_conventionsgroup has three pages and onlyattestation_typesis linked from anywhere; itsoverviewandflows_and_trailssiblings are not.URL impact
None. No page files move, no navigation entries change, no headings are renamed. This is adding links to prose, so no
config/redirects.jsonentry is needed.What a fix looks like
Add one contextual link from each page in the right-hand column. Not a "See also" dump — a sentence where the subject actually comes up. The GKE line in
getting_started/environments.mdis the model: the sibling list already exists, the entry is just missing.Worth doing alongside #395 rather than after it, since the same pages change hands there.
Evidence
Nav pages, minus generated trees, minus everything that appears as a link target anywhere in the repo:
The difference is the table above.
changelog/indexandlabs/indexalso appear in the difference and are excluded as false positives — both are linked by their tab path (/changelog,/labs).Found by the monthly doc-structure audit, step 2 (cross-reference rot).