Skip to content

docs: restructure documentation and rewrite in Simplified Technical English - #2530

Merged
esnible merged 4 commits into
mainfrom
docs/restructure-information-architecture
Sep 10, 2026
Merged

docs: restructure documentation and rewrite in Simplified Technical English#2530
esnible merged 4 commits into
mainfrom
docs/restructure-information-architecture

Conversation

@Ibrahim2595

@Ibrahim2595 Ibrahim2595 commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

What & why

docs/ is both the team's engineering workspace and the source for rossoctl.dev. Because the site sidebar is autogenerated from this folder tree, the published information architecture ended up being a by-product of which files carried draft: true rather than a decision anyone made.

What that produced today:

Markdown files in docs/ ~200
Pages actually published 20
Top-level sidebar sections 5
Reference pages (CLI, CRDs, config, glossary) 0

Three concrete problems fall out of that:

  1. The docs disagree on what Rossoctl is. overview/1-what-is.md calls it a data plane controller; concepts/components.md calls it middleware for orchestrating agents on Kubernetes. The README's three-part model (RossoCortex, services, tooling) is clearer than either, and is not in the docs at all.
  2. The five-minute path is invisible. Cortex runs as one binary on a laptop and shows an agent's traffic in about a minute. That lives only in the cortex README. The docs site opens with 18 GiB of RAM, six cores, kind, and a git clone.
  3. Nothing states what is safe to depend on. Identity and authorization are Ready; IBAC and SPARC are beta; context compaction and data-flow analysis are alpha. That table exists only in the README, so the sidebar presents alpha plugins and production install steps as peers.

What this changes

43 pages in six sections, ordered by how much a reader has to commit before the next section pays off. The whole set is written in ASD-STE100 (Simplified Technical English).

# Section Pages For
Introduction (docs/index.md) 1 What Rossoctl is, and where to start
1 Get started 7 Laptop quickstart (~5 min), Kubernetes quickstart (~20 min), first agent, first tool, CLI
2 Concepts → Core 6 The five features every installation uses. All Ready.
2 Concepts → Experiments 8 Features that are not production-ready. Each page states its maturity.
3 Agents and tools 4 Bring your own agent, deploy an agent, deploy a tool
4 Security 5 Workload identity, AuthBridge, authentication modes, flows
5 Install and operate 6 Three install targets, observability, troubleshooting
6 Reference 5 CLI, custom resources, install options, glossary
Resources (docs/resources.md) 1 Demonstrations, examples, community

Simplified Technical English

Short sentences, active voice, present tense, one term per concept, no contractions, no idioms, no metaphors. Measured across the 1,539 prose sentences in the published set:

Check Result
Sentences over the 25-word descriptive limit 0.3% (5 of 1,539)
Contractions 0
Non-approved words (via, e.g., etc., utilize, leverage) 0
Vague modals (should, might, could, maybe) 0

The rewrite removes no information.

Consolidation

Nine top-level sections became six, and 47 pages became 43. The larger gain is that the nine /docs/category/* pages of cards are gone: each _category_.json now links to its own section introduction, so a section has one landing page instead of two. Total routes drop from 56 to 43.

  • overview/ is removed. "What is Rossoctl", the problem statement and the path router are now one page: docs/index.md. The maturity table moves to concepts/index.md, beside the core/experiment split it explains. overview/architecture.md becomes concepts/core/architecture.md.
  • guardrails/ is removed. Every feature in it is an experiment, so each page moves to concepts/experiments/. This keeps the original intent — alpha plugins must not sit beside Ready guarantees — and states it more plainly.
  • resources/ becomes one page.

Core and Experiments

The split follows the project's own classification. The organization profile marks each repository as core or experimental, and the plugin catalogue gives the maturity of each RossoCortex plugin.

Core (Ready) Experiments (Beta or Alpha)
Architecture · Agents and tools · RossoCortex · Identity and trust · Control plane MCP Gateway (Kuadrant) · Skills · Sandboxes (OpenShell fork, upstream agent-sandbox) · Agent context (context-service) · Intent-based access · Tool call validation · Context compaction (context-guru) · Cost control

Each experiment page opens with its maturity level. concepts/index.md states that a reader can skip the whole group, and that an installation with no experiment is complete and supported.

concepts/experiments/sandboxes.md is new. It documents the two manual steps a Sandbox resource needs today, and names the related repositories (OpenShell, openshell-driver-openshift, serverless-harness).

What I deliberately did not write

I proposed 79 pages and wrote 47. Everything dropped was either not grounded in shipped work or would have added confusion. Nothing here describes behaviour that is not implemented.

Dropped Why
security/policy-engines, audit-and-governance, hardening CPEX is "converging on", Praxis "emerging", data governance is a private epic. Writing these meant inventing.
guardrails/failure-recovery, data-flow-analysis Shipped capabilities with no implementation docs anywhere. Named honestly in overview/capabilities.md instead of omitted.
operate/upgrade, scaling, multi-tenancy, load-testing No source material. operate/index.md has a "Not yet documented" section naming them.
reference/rest-api, helm-values Cannot be hand-written accurately. reference/index.md points at the schema and the chart.
Stale demo pages Seven of ten were draft: true and some reference a legacy UI. Replaced with a curated resources/demos.md.

Where behaviour is rough — sandbox pod restarts, context deletion having no dependency guard, the MCP Gateway's missing auth — the pages say so in a warning admonition rather than omitting it.

One naming decision worth knowing about

The "Build agents and tools" section lives at docs/workloads/, not docs/build/.

This repo's .gitignore has a bare build/ rule — intended for build output, but it matches any directory with that name at any depth. The first version of this branch used docs/build/, and git add -A silently dropped all 8 files. Nothing warned; the section simply was not in the commit, and a local build still passed because it read from the working tree rather than from what had been pushed. A fresh clone of the branch is what surfaced it.

I renamed the folder rather than git add -f-ing it. Force-adding leaves the trap in place for the next person who adds a page there, and other ignore-aware tooling — Docker builds, rsync --exclude-from — would skip it too. workloads also matches the platform's own vocabulary (rossoctl.io/type, workload identity).

The reader-facing sidebar label is unchanged. Only the URL moved, to /docs/workloads/*.

If you would rather keep /docs/build/ as the URL, the alternative is narrowing the ignore rule to /build/ (root-anchored, which is almost certainly the original intent) — happy to do that instead.

Also in this change, because the move requires it

  • SVG diagrams move docs/concepts/docs/images/, which is where CONTRIBUTING.md says architecture diagrams belong. docs/diagrams/ is untouched.
  • Repo-root cross-references repointed — README, CONTRIBUTING, CLAUDE, CLAUDE-ORG, SECURITY, PERSONAS_AND_ROLES, FEATURE_ACCEPTANCE. The README documentation table is rewritten to match the new structure.

Rebased onto #2545

#2545 landed while this branch was open. It changed the two pages that this branch replaces, so I read it rather than resolve the conflict mechanically, and carried both of its corrections:

  • The viewer command is abctl observe, not abctl. This branch had the earlier form in the laptop quickstart, in cost control and in observability. Verified against the current cortex README.
  • The rossoctl page is now "Install the cluster CLI", which separates it from abctl. The CLI page and the glossary now state that the two programs are separate, because the earlier names invited confusion.

The conflict itself was a modify/delete on docs/getting-started/install-cli.md and install-local.md. Both are superseded by docs/get-started/, so the deletions stand and the substance is carried across.

How this was validated

Built with Docusaurus 3.10.1 against a clone of rossoctl/.github, using sync-docs.sh's own rsync so the docs source is exactly what CI will see:

  • 43 routes generated, zero broken links, zero warnings. (56 before consolidation; the 13 removed are the 9 category card pages and 4 merged pages.)
  • docs/_internal/, docs/images/, and docs/diagrams/ correctly produce no routes.
  • All 245 internal links and every heading anchor resolve.
  • No repo-root or published-docs link is left broken.

Findings from that build, all handled in the companion PR to rossoctl/.github (rossoctl/.github#120):

  1. The site config's exclude: array replaces Docusaurus's defaults, which include **/_*/**. That default is what keeps docs/_internal/** out of the build — with an explicit exclude present, internal notes get compiled and the build fails on their relative image links. The companion PR removes it.
  2. sidebars.ts wraps everything in a redundant "Documentation" category. The companion PR drops it so docs/index.md becomes the /docs/ landing page.

This PR cannot merge before that one, or the site build will fail on docs/_internal/.

Pre-existing issues found but not fixed here

Left alone to keep this PR to one purpose:

  • 60 already-broken relative links inside the docs that moved to _internal/ — targets like ../CLEANUP-TEST-RESULTS.md and ../ARCHITECTURE-4.21.md that do not exist on main either. I fixed the 6 breakages this move actually caused; these 60 predate it.
  • IBAC and SPARC have two published statuses. rossoctl.dev and this README say "beta in 0.7"; the cortex plugin catalog says both are Alpha. These pages use the published beta status. Someone should reconcile the two.
  • --with-agent-sandbox appears in this README's install command but not in the installer's own documented flag table. The docs use only documented flags.

Reviewing this

The diff is large (204 files) because the IA only works as a whole — a half-migrated tree has a worse sidebar than either end state. Suggested order:

  1. docs/index.md — the entry point and the product story.
  2. docs/concepts/index.md — the core/experiment split and the maturity table. Check every claim against what you know.
  3. docs/get-started/laptop.md and kubernetes.md — the two paths a new user takes.
  4. Your own area, wherever that is.

Corrections to technical claims are the most valuable thing here. I wrote from the repos, the READMEs, and the plugin catalog — not from running every path.

Acceptance tier

  • Tier 0 — Maintenance (bugfix / docs / dependency bump / no-behavior refactor)

Checklist

Pillar 1 — Code quality

  • Follows repo conventions (diagram locations per CONTRIBUTING.md; no Co-Authored-By trailer)
  • DCO sign-off on all commits (git commit -s), commit SSH-signed and verified
  • No code changed — documentation and repo-root cross-references only

Pillar 2 — Documentation

  • Docs affected by this change are updated — this change is the docs
  • Verified with a real Docusaurus build: 56 routes, zero broken links, zero warnings

Tiers 3 and 4 do not apply to a Tier 0 documentation change.


Assisted-By: Claude Code

@mrsabath mrsabath 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.

Reviewed the full 204-file diff, all seven repo-root cross-reference edits, and the CI Link Check failure. Verified link targets against the diff and against main. Not approving yet — leaving findings for you and the maintainers to weigh, since the one real point is a decision rather than a defect.

This is a careful, unusually well-documented Tier-0 restructure. The IA is coherent, the "what I deliberately did not write" and "pre-existing issues" sections are exactly the disclosures a reviewer wants, and the docs/build/docs/workloads/ .gitignore catch is a genuinely good find. The repo-root repoints (README, SECURITY, CONTRIBUTING, …) all target files that exist in the new tree, and the stale docs/concepts/* references I spot-checked are all on removed lines (the old README table being replaced).

The Link Check failure will not self-resolve — worth a decision before merge

The repo's own link gate (.lychee.toml) scans all markdown, including docs/_internal/. It does not mirror Docusaurus's _-prefix exclusion. So:

  • Your Docusaurus validation (56 routes, zero broken links) is correct for the site — it ignores _internal/.
  • The repo's lychee job does not ignore _internal/, so it re-scans the ~60 pre-existing broken relative links you flagged. 16 of the 17 error-source files are under docs/_internal/.
  • The lone non-_internal error is SECURITY.md:12 — the ../../security/advisories/new GitHub-relative URL, which lychee's offline mode misreads as a local file. That predates this PR (it's on main) and your edit only touched line 59. False positive.

Net: the PR introduces no new broken links, but because the moved files now live where lychee re-scans them, this required check stays red on merge. Three ways to resolve, in rough order of preference:

  1. Add docs/_internal to exclude_path in .lychee.toml — parallels the Docusaurus _-prefix exclusion, so the repo gate and the site build agree on what's internal. Smallest change, fixes the class rather than the instances.
  2. Fix the ~60 pre-existing _internal/ links in this PR (larger scope; you deliberately scoped these out, which is reasonable).
  3. Maintainer acknowledges / overrides the check.

I'd lean (1). Flagging so it's a conscious call and not a surprise red X at merge time.

Areas reviewed: Docs (204 files), repo-root cross-refs, CI (Link Check analyzed), commit/PR conventions.
Commits: 1, signed off (SSH-signed; Assisted-By: Claude).
CI: 20 pass, 1 fail (Link Check — pre-existing _internal/ links, analysis above), 2 skipped.

One cosmetic nit inline. Nice work — this is a hard change to get right and the write-up made it reviewable.

Comment thread CLAUDE.md Outdated
| Git | `git:worktree` |

See [docs/concepts/skills.md](docs/concepts/skills.md) for the skill index and [docs/developer/README.md](docs/developer/README.md) for Claude Code workflows.
See [docs/concepts/skills.md](docs/workloads/skills.md) for the skill index and [docs/developer/README.md](docs/_internal/developer/README.md) for Claude Code workflows.

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 (cosmetic, non-blocking): the link targets are correctly repointed — docs/workloads/skills.md and docs/_internal/developer/README.md both exist and resolve — but the display text still reads the old paths (docs/concepts/skills.md and docs/developer/README.md). lychee passes these (it checks targets, not link text), so it's purely a reader-facing mismatch in a maintainer file. Worth a one-line touch-up while you're here:

See [docs/workloads/skills.md](docs/workloads/skills.md) for the skill index and [docs/_internal/developer/README.md](docs/_internal/developer/README.md) for Claude Code workflows.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch, fixed in 91a944c.

The path moved once more in the consolidation commit, so the line now reads:

See [docs/concepts/experiments/skills.md](docs/concepts/experiments/skills.md) for the skill index and [docs/_internal/developer/README.md](docs/_internal/developer/README.md) for Claude Code workflows.

Skills became an experiment in the second commit, hence concepts/experiments/ rather than workloads/. I checked the rest of CLAUDE.md for the same class of mismatch: the other six docs links use descriptive labels such as "Installation Guide" and "Components", so there is no path text to fall out of date, and all six targets resolve.

@Ibrahim2595 Ibrahim2595 changed the title docs: restructure documentation into a task-based information architecture docs: restructure documentation and rewrite in Simplified Technical English Sep 9, 2026
…cture

The docs/ folder is both the team's engineering workspace and the source for
rossoctl.dev, so the published information architecture was a by-product of
which files happened to carry `draft: true` rather than a decision anyone made.
Of roughly 200 markdown files, 20 reached readers, spread across five categories
with no reference section, no canonical getting-started path, and two pages that
disagreed on what Rossoctl is.

This replaces the published tree with 47 pages in nine sections, ordered by how
much a reader has to commit before the next section pays off: read, run a binary,
run a cluster, wire in your own agent, secure it, add optional guardrails, operate
it. Because the site sidebar is autogenerated from this folder tree, the structure
here is the navigation.

Engineering material — plans, research, retrospectives, design proposals, QA
matrices, developer setup — moves to docs/_internal/. Docusaurus excludes
`_`-prefixed paths by default, which retires every `draft: true` flag and the
site config's exclude list, and keeps internal notes out of future version
snapshots.

Content is derived from existing material in this repo and from the cortex,
operator, and rossoctl-cli READMEs. Nothing describes behaviour that is not
already implemented; capabilities that ship without documentation are named as
such in docs/overview/capabilities.md rather than omitted.

The "Build agents and tools" section lives at docs/workloads/, not docs/build/:
the repo's .gitignore has a `build/` rule, which silently excludes any directory
with that name from commits. The reader-facing label is unchanged.

Also in this change, because the move requires it:
- SVG diagrams move from docs/concepts/ to docs/images/, per CONTRIBUTING.md.
- Repo-root files (README, CONTRIBUTING, CLAUDE, SECURITY, and others) are
  repointed at the new paths. No repo-root or published-docs link is left broken.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: IBRAHIM IBRAHIM <66755652+Ibrahim2595@users.noreply.github.com>
…nglish

Review feedback on the first version of this branch asked for three changes.

1. Write in ASD-STE100 (Simplified Technical English).

Every page is rewritten. Short sentences, active voice, present tense, one term
for one concept, no contractions, no idioms and no metaphors. Measured over the
1,539 prose sentences: 0.3 percent are longer than the 25-word limit for
descriptive text, there are no contractions, and there are no vague modal verbs.
The rewrite removes no information.

2. Consolidate the structure.

Nine top-level sections become six, and 47 pages become 43. More important, the
nine `/docs/category/*` pages of cards are gone: each `_category_.json` file now
links to the introduction page of its own section, so a section has one landing
page and not two.

- The `overview/` section is removed. "What is Rossoctl", the problem statement
  and the router of paths are now one page, `docs/index.md`. The maturity table
  moves to `concepts/index.md`, next to the core and experiment split that it
  explains. `overview/architecture.md` becomes `concepts/core/architecture.md`.
- The `guardrails/` section is removed. Each of its features is an experiment, so
  each page moves to `concepts/experiments/`.
- `resources/` becomes one page, `docs/resources.md`.

3. Divide Concepts into Core and Experiments.

The division follows the Rossoctl organization profile, which marks each
repository as core or experimental, and the RossoCortex plugin catalogue.

- **Core** holds the five features that every installation uses and that are
  ready for production: architecture, agents and tools, RossoCortex, identity and
  trust, and the control plane.
- **Experiments** holds eight features that are not ready for production: the MCP
  Gateway (Kuadrant), skills, sandboxes (the OpenShell fork and the upstream
  agent-sandbox project), agent context (context-service), intent-based access,
  tool call validation, context compaction (context-guru) and cost control.

Each experiment page starts with its maturity level. `concepts/index.md` states
that a reader can ignore the group, and that an installation with no experiment
is complete and supported.

`concepts/experiments/sandboxes.md` is a new page. It documents the two manual
steps that a `Sandbox` resource needs today, and names the related repositories.

Repo-root files are repointed at the new paths. No repo-root link and no
published-docs link is broken.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: IBRAHIM IBRAHIM <66755652+Ibrahim2595@users.noreply.github.com>
Upstream #2545 renamed the CLI page and corrected the viewer command. This branch
replaces the pages that #2545 changed, so it must carry those two corrections.

- The viewer command is `abctl observe`, not `abctl`. This branch had the earlier
  form in the laptop quickstart, in cost control and in observability.
- The `rossoctl` CLI page is now "Install the cluster CLI", which separates it from
  `abctl`, the program for a computer. The CLI page and the glossary state that the
  two programs are separate, because the earlier names invited confusion.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: IBRAHIM IBRAHIM <66755652+Ibrahim2595@users.noreply.github.com>
@Ibrahim2595
Ibrahim2595 force-pushed the docs/restructure-information-architecture branch from f0bf254 to 8b2ba81 Compare September 9, 2026 19:40
Ibrahim2595 added a commit to rossoctl/.github that referenced this pull request Sep 9, 2026
rossoctl/rossoctl#2530 restructures docs/ into nine task-based sections and moves
the team's engineering notes to docs/_internal/. Three things in this repo have to
change for that to build, and one landing-page link has to move.

1. docusaurus.config.ts — the docs plugin's `exclude` option REPLACES Docusaurus's
   defaults rather than extending them, so setting it silently dropped the default
   '**/_*/**' rule. That rule is what keeps docs/_internal/** out of the build;
   without it those notes are compiled and the build fails on their repo-relative
   image links. The defaults are now repeated explicitly, with a comment saying
   why they must stay. The legacy superpowers/authbridge/automation-health entries
   are kept so this config is correct whichever order the two PRs land in.

2. sidebars.ts — drop the wrapping "Documentation" category. It added a redundant
   level above the nine real sections, and its generated-index claimed the /docs/
   route that docs/index.md now owns.

3. scripts/sync-docs.sh — exclude _internal from the mirror. Docusaurus would
   ignore it anyway, but keeping it out of the site tree matters for versioning:
   `docusaurus docs:version` snapshots whatever is in docs/ into a committed
   versioned_docs/ folder, so otherwise every release would freeze a copy of the
   team's plans and retrospectives into this repo. The README slug hack is also
   removed, since the new tree has no docs/README.md, and a temporary fallback
   synthesises docs/index.md while upstream has none.

4. ecosystem/welcome.mdx — the "Get started" CTA pointed at /docs/overview/quickstart,
   which the restructure removes. It now points at /docs/, which is valid before and
   after the restructure and is itself a router.

Verified by running scripts/sync-docs.sh against both the current upstream docs and
the restructure branch, then building each. Both orders succeed with zero broken
links and zero internal pages published.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: IBRAHIM IBRAHIM <66755652+Ibrahim2595@users.noreply.github.com>

@esnible esnible left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Summary

Documentation restructure: 208 files, +5,444/−8,014, moving 103 engineering files into docs/_internal/ and rewriting the published set as 44 pages across six sections in ASD-STE100.

I verified the claims in the description rather than taking the self-reported tables at face value:

Claim Verified
0 contractions ✅ 0 across the 44 published pages
0 non-approved words (via, e.g., etc., utilize, leverage) ✅ 0
0 vague modals (should, might, could, maybe) ✅ 0
Nine /docs/category/* card pages gone ✅ all 8 _category_.json link to their own index; no generated-index remains
43 pages in six sections ✅ 44 .md (43 + diagrams/) in exactly the six advertised sections
The build/ gitignore trap .gitignore:11 is a bare build/; git check-ignore -v docs/build/test.md confirms it would be silently dropped
docs/index.md carries slug: / ✅ present

I also ran an independent relative-link check across all 44 published pages: 0 broken.

On the sentence-length figure — my first pass appeared to contradict the stated 0.3%, but that was my measurement being wrong, not the PR. Stripping code fences fuses a colon-ending lead-in with the sentence after the block into one apparent 30-word sentence (one case even glued image alt-text onto the next sentence). The 0.3% figure is the credible one.

The failing Link Check

Worth being precise, because the headline "fail" overstates it.

40 of the 41 errors are in docs/_internal/** — unpublished engineering notes — and all share one mechanical cause: files moved down a directory level (docs/dev-guide.mddocs/_internal/dev-guide.md, 100% similarity, pure move), so repo-root-relative links like ../CLAUDE.md now land one level short. That is what produces the docs/CLAUDE.md and docs/.github/scripts/... paths in the log. They need ../../.

The 41st error, in SECURITY.md, is pre-existing and not caused by this PR. The failing link is ../../security/advisories/new at line 12:4, byte-identical on upstream/main; lychee cannot resolve GitHub's relative-advisory-URL convention against the filesystem. This PR's only SECURITY.md change is at line 62, retargeting the moved install guide, and it is correct.

So the published surface is clean and the remaining work is confined to _internal link depth. I have marked those as suggestions rather than must-fix because they affect no published page. CI is red, though, so it needs resolving before merge one way or the other — either correct the depths, or scope lychee to skip unpublished notes, which would also stop this recurring on every future reorganisation of that tree.

Cross-repo integration (checked, and correct)

This is the upstream counterpart to rossoctl/.github#120. That PR's sync-docs.sh carries a "MIGRATION WINDOW" shim that synthesises docs/index.md only when upstream does not provide one, and excludes _internal from the rsync. Both assumptions hold against this branch: docs/index.md exists with slug: /, so the shim correctly degrades to a no-op, and _internal never reaches the site. The two PRs interlock as each describes.

Author: Ibrahim2595 (MEMBER — maintainer)
Areas reviewed: Docs/Markdown, YAML (_category_.json), gitignore semantics, CI link checking, cross-repo site integration
Agent/IDE config (.claude/.vscode): none
Commits: 3, all signed-off (DCO passing)
CI status: 22 passing, 1 failing (Link Check — analysed above)

The _internal link fixes

Both findings below were drafted as inline comments, but these files are 100%-similarity renames with no changed lines, so GitHub has no diff hunk to anchor to. Recording them here instead.

docs/_internal/dev-guide.md../CLAUDE.md (line 57) is one level short after the move and now resolves to the non-existent docs/CLAUDE.md; it needs ../../CLAUDE.md. Same problem in the same file for .github/scripts/hypershift/setup-hypershift-ci-credentials.sh, ARCHITECTURE-4.21.md, CLEANUP-TEST-RESULTS.md, PERSONAS_AND_ROLES.md, QUICKSTART-4.21.md, and terraform/README.md.

docs/_internal/developer/README.md — same pattern for .claude/skills/README.md, .github/scripts/local-setup/README.md, _internal/concepts/components.md, and two references to _internal/getting-started/install.md.

Since this recurs on every reorganisation of this tree, excluding docs/_internal/ from the lychee config is probably the better fix than correcting depths by hand — these pages are never published, so the checker is guarding output nobody reads.

… gate

Review feedback from @mrsabath and @esnible on the failing Link Check. Both
identified the cause and both preferred scoping lychee over correcting the paths
one at a time. This does the scoping, and also corrects every link that this
branch broke, because an internal page that a maintainer opens on GitHub should
still work.

Corrected, all of them caused by this branch:

- 30 links in docs/_internal/ that lost one directory level. The files moved from
  docs/ to docs/_internal/, so a link such as `../CLAUDE.md` resolved to
  docs/CLAUDE.md. Each one now has the correct depth.
- 9 links in docs/_internal/ that pointed at a published page which this branch
  moved or replaced. They now point at the new page, for example
  `../concepts/identity-guide.md` becomes `../../security/authbridge.md`.
- 6 links outside docs/ that pointed into the moved tree, in
  deployments/openshell/, rossoctl/examples/ and rossoctl/demo-setup/. The Link
  Check reads only the files that a pull request changes, so it did not report
  these: the files did not change, their targets moved.

Also in this change:

- .lychee.toml excludes docs/_internal. Docusaurus already excludes that tree from
  the site through its default '**/_*/**' rule, so nothing in it is published.
  The exclusion keeps the gate and the site build in agreement about what is
  internal, and it stops a later reorganisation of that tree from turning the gate
  red for links that no reader can reach. 20 links in there were already broken on
  main; this branch does not repair them, and they are now out of the gate.
- SECURITY.md gives an absolute address for the GitHub advisory form. The previous
  `../../security/advisories/new` is a GitHub convention that no link checker can
  resolve against the file system, and it was the one error outside
  docs/_internal. It is byte-identical on main, so this corrects a defect that
  predates this branch.
- CLAUDE.md shows the correct path in the text of two links. The targets were
  already correct; the text still read the earlier paths.

Verified across every markdown file in the repository, with the exclude_path list
from .lychee.toml applied: 0 links broken by this branch, and 5 that were already
broken on main and stay outside its scope.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: IBRAHIM IBRAHIM <66755652+Ibrahim2595@users.noreply.github.com>
Ibrahim2595 added a commit to rossoctl/.github that referenced this pull request Sep 10, 2026
rossoctl/rossoctl#2530 restructures docs/ into nine task-based sections and moves
the team's engineering notes to docs/_internal/. Three things in this repo have to
change for that to build, and one landing-page link has to move.

1. docusaurus.config.ts — the docs plugin's `exclude` option REPLACES Docusaurus's
   defaults rather than extending them, so setting it silently dropped the default
   '**/_*/**' rule. That rule is what keeps docs/_internal/** out of the build;
   without it those notes are compiled and the build fails on their repo-relative
   image links. The defaults are now repeated explicitly, with a comment saying
   why they must stay. The legacy superpowers/authbridge/automation-health entries
   are kept so this config is correct whichever order the two PRs land in.

2. sidebars.ts — drop the wrapping "Documentation" category. It added a redundant
   level above the nine real sections, and its generated-index claimed the /docs/
   route that docs/index.md now owns.

3. scripts/sync-docs.sh — exclude _internal from the mirror. Docusaurus would
   ignore it anyway, but keeping it out of the site tree matters for versioning:
   `docusaurus docs:version` snapshots whatever is in docs/ into a committed
   versioned_docs/ folder, so otherwise every release would freeze a copy of the
   team's plans and retrospectives into this repo. The README slug hack is also
   removed, since the new tree has no docs/README.md, and a temporary fallback
   synthesises docs/index.md while upstream has none.

4. ecosystem/welcome.mdx — the "Get started" CTA pointed at /docs/overview/quickstart,
   which the restructure removes. It now points at /docs/, which is valid before and
   after the restructure and is itself a router.

Verified by running scripts/sync-docs.sh against both the current upstream docs and
the restructure branch, then building each. Both orders succeed with zero broken
links and zero internal pages published.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: IBRAHIM IBRAHIM <66755652+Ibrahim2595@users.noreply.github.com>
@Ibrahim2595

Copy link
Copy Markdown
Contributor Author

Thanks @mrsabath and @esnible — the link analysis in both reviews was more precise than mine, and it found a class of breakage I had missed entirely.

Link Check now passes. Fixed in 91a944c.

I took your recommended fix, and also repaired what I broke

You both preferred scoping lychee over correcting paths one at a time. I did the scoping, and also corrected every link this branch broke — an internal page a maintainer opens on GitHub should still work, even though no reader sees it.

Count Action
_internal links that lost one directory level 30 Corrected the depth
_internal links pointing at a published page this branch moved 9 Repointed, e.g. ../concepts/identity-guide.md../../security/authbridge.md
Links outside docs/ pointing into the moved tree 6 Repointed
_internal links already broken on main 20 Left alone, now outside the gate

.lychee.toml now excludes docs/_internal, with a comment explaining that Docusaurus already excludes the tree via its default **/_*/** rule, so the gate and the site build agree on what is internal.

The 6 links CI could not have caught

This is the part your reviews led me to and I would otherwise have shipped broken.

Both of you correctly scoped the failure to _internal plus SECURITY.md. That is what the gate reported — but the gate reads only the files a PR changes. Links in files this PR does not touch, whose targets it moved, are invisible to it:

deployments/openshell/README.md                        -> docs/agentic-runtime/openshell-integration.md
rossoctl/demo-setup/keycloak-config/slack/README.md    -> docs/demos/demo-slack-research-agent.md
rossoctl/examples/app-demo/README.md                   -> docs/developing-rossoctl-app.md  (x2)
rossoctl/examples/app-demo/README.md                   -> docs/concepts/identity-guide.md
rossoctl/examples/simulated-tools/tasks-api/README.md  -> docs/new-simulated-tool.md

All six now point at the new locations. To find them I checked every markdown file in the repository against main, applying .lychee.toml's exclude_path, and classified each broken link by whether its target existed on main:

broken by this PR: 0
pre-existing (broken on main too, left alone): 5

Worth noting for the future: the changed-files filter means a move can break links that CI never sees. A periodic full-repo run would close that gap.

SECURITY.md

@esnible — you were right that it is byte-identical on main, so it predates this branch. But because this PR touches the file, the filter includes it and it was the one error outside _internal. Rather than exclude it, I gave the advisory form its absolute address:

-[GitHub Security Advisories](../../security/advisories/new)
+[GitHub Security Advisories](https://github.com/rossoctl/rossoctl/security/advisories/new)

That is correct regardless of where the file sits, and it removes a defect rather than hiding it.

On the measurement disagreement

@esnible — thank you for re-checking your own sentence-length result and reporting that it was your measurement rather than the PR. That is a generous thing to do in a review, and you diagnosed the exact failure mode I hit when I first wrote the checker: stripping code fences fuses a colon-terminated lead-in with the sentence after the block. My final pass treats a fence as a sentence boundary for that reason.

Verified after these changes

  • Whole-repo link classification: 0 broken by this PR.
  • Docusaurus build from this branch: 43 dev routes, 0 broken links, 0 warnings; v0.7 stays frozen at 27; nothing under _internal reaches the site.
  • Link Check: pass.

Assisted-By: Claude Code

@Ibrahim2595

Copy link
Copy Markdown
Contributor Author

Status update

Both review threads are resolved and all checks pass. Approved by @esnible; @mrsabath's findings are all addressed.

Three things worth putting on the record before merge.

1. The merge order still matters — re-verified after #121 landed

rossoctl/.github#121 merged, so both site PRs now target main and the original three-way stack is gone. That could give the impression the ordering no longer applies. It does.

I tested this branch against current .github@main rather than reasoning about it:

main head: 1cadb8b  (site: cut docs version 0.7 ... #121)
build: SUCCESS
internal pages published: 6
  /docs/dev/_internal/automation-health
  /docs/dev/_internal/authbridge/opa-migration-guide
  /docs/dev/_internal/superpowers/plans/2026-07-21-feature-acceptance-standard
  /docs/dev/_internal/superpowers/specs/2026-07-21-feature-acceptance-standard-design
  /docs/dev/_internal/superpowers/specs/2026-08-24-mesh-selfheal-detection-ttl-design
  /docs/dev/_internal/superpowers/specs/2026-07-28-cortex-components-doc-design

#121 did not touch the exclude array, so main still carries the pre-restructure list. Because providing exclude replaces Docusaurus's defaults, **/_*/** is absent and docs/_internal/ compiles.

rossoctl/.github#120 must merge before this PR, or six pages of engineering notes appear at /docs/dev/_internal/* on the public site. #120 is approved and mergeable.

2. The remaining broken links, counted precisely

@mrsabath estimated ~60 and @esnible counted 40 from the CI log. Both were reading the pre-fix state. Here is the audited figure now, across every markdown file in the repository:

Count
Broken by this PR 0
Pre-existing, in docs/_internal/ (now outside the gate) 18
Pre-existing, outside docs/ 2
Cross-repo paths into a sibling cortex/ checkout 3
Not links at all — false positives in my own checker 2

The two false positives are worth naming so nobody chases them:

  • docs/_internal/plans/2026-02-15-…-impl.md:325 is a Python regex in a code sample: re.search(r'-m\s+["\'](.+?)["\']', cmd). A naive ](…) pattern matches ](.+?).
  • docs/_internal/svg-diagram-style-guide.md:79 is a syntax example: `![Alt text](./diagram-name.svg)`. No such file exists, by design.

So the real residue is ~20 dead references in unpublished notes, every one of them already broken on main. None affects a published page, and this PR introduces none.

3. Excluding docs/_internal reduces coverage — deliberately

Both of you recommended the exclusion and I agree with it, but it is a trade rather than a free win, so it should be explicit: that tree is now unguarded. A new dead link in an internal note will not fail CI, and the 18 above will not be caught again.

The reasoning for accepting that: the gate was validating pages no reader reaches, and it would have turned red on every future reorganisation of the tree. If the team would rather keep it guarded, the alternative is to fix the 18 and drop the exclusion — happy to do that instead.

A CI gap this exposed, worth a separate look

The Link Check reads only the files a pull request changes. A move therefore breaks links in files the PR does not touch, and the gate cannot see it. That is how six links in deployments/openshell/, rossoctl/examples/ and rossoctl/demo-setup/ nearly shipped broken — CI was green on them throughout.

A periodic full-repository run would close it. That is a CI-design decision rather than part of this change, so I have not opened an issue; flagging it for whoever owns the workflow.

Ready to merge


Assisted-By: Claude Code

@esnible
esnible merged commit 802f615 into main Sep 10, 2026
30 of 32 checks passed
@esnible
esnible deleted the docs/restructure-information-architecture branch September 10, 2026 18:09
@github-project-automation github-project-automation Bot moved this from New/ToDo to Done in Rossoctl Issue Prioritization Sep 10, 2026
esnible pushed a commit to rossoctl/.github that referenced this pull request Sep 10, 2026
…aphy (#120)

* site: support the restructured docs information architecture

rossoctl/rossoctl#2530 restructures docs/ into nine task-based sections and moves
the team's engineering notes to docs/_internal/. Three things in this repo have to
change for that to build, and one landing-page link has to move.

1. docusaurus.config.ts — the docs plugin's `exclude` option REPLACES Docusaurus's
   defaults rather than extending them, so setting it silently dropped the default
   '**/_*/**' rule. That rule is what keeps docs/_internal/** out of the build;
   without it those notes are compiled and the build fails on their repo-relative
   image links. The defaults are now repeated explicitly, with a comment saying
   why they must stay. The legacy superpowers/authbridge/automation-health entries
   are kept so this config is correct whichever order the two PRs land in.

2. sidebars.ts — drop the wrapping "Documentation" category. It added a redundant
   level above the nine real sections, and its generated-index claimed the /docs/
   route that docs/index.md now owns.

3. scripts/sync-docs.sh — exclude _internal from the mirror. Docusaurus would
   ignore it anyway, but keeping it out of the site tree matters for versioning:
   `docusaurus docs:version` snapshots whatever is in docs/ into a committed
   versioned_docs/ folder, so otherwise every release would freeze a copy of the
   team's plans and retrospectives into this repo. The README slug hack is also
   removed, since the new tree has no docs/README.md, and a temporary fallback
   synthesises docs/index.md while upstream has none.

4. ecosystem/welcome.mdx — the "Get started" CTA pointed at /docs/overview/quickstart,
   which the restructure removes. It now points at /docs/, which is valid before and
   after the restructure and is itself a router.

Verified by running scripts/sync-docs.sh against both the current upstream docs and
the restructure branch, then building each. Both orders succeed with zero broken
links and zero internal pages published.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: IBRAHIM IBRAHIM <66755652+Ibrahim2595@users.noreply.github.com>

* site: tune documentation typography for long-form reading

The site-wide type scale is tuned for the landing page, and on a reference page
it read as bulky. Two things caused it:

- h1 was 3rem against 0.875rem body text — a 3.4x jump — so every heading
  shouted relative to the prose around it.
- h3, h4, h5 and h6 were all 1.5rem, so anything below an h2 had no visible
  hierarchy. On a page like the CLI reference that flattens the whole structure.

This adds a reading scale for documentation pages: body 1rem/1.7, h1 2.25rem,
h2 1.5rem, h3 1.1875rem, h4 1rem — a 2.25x jump from body to h1 instead of
3.4x — plus a hairline rule under each h2, which is what makes section
boundaries findable while scrolling.

Supporting changes, all in the same direction:

- IBM Plex Mono for code, self-hosted via @fontsource like the sans already is,
  so code and prose share one design language.
- The first paragraph after the title renders as a standfirst. Every page in the
  restructured docs opens with a one- or two-sentence orientation, so this is
  hierarchy from content that already exists.
- Line length capped at ~72 characters; tables, code blocks and diagrams break
  out to the full column width.
- Tables get a light header fill, hairline borders and roomier cells, and lose
  the zebra striping.
- Inline code loses its border — a border on every symbol name made reference
  pages look like forms.
- Sidebar section headings and the table of contents become small, quiet,
  letter-spaced labels.
- Body links are underlined. Brand red without an underline reads as emphasis
  rather than as a link.

Scoped to `html.plugin-id-default` and `.plugin-id-contributing`, the classes
Docusaurus puts on <html>, so the ecosystem landing page is untouched and keeps
its 3rem hero. Stable theme classes and Infima variables only — nothing
swizzled, no hashed class names — and both light and dark palettes are defined.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: IBRAHIM IBRAHIM <66755652+Ibrahim2595@users.noreply.github.com>

* site: address review feedback on the rsync exclude and the version path

Two nits from @esnible, neither blocking.

- scripts/sync-docs.sh: the rsync exclude was `_internal`, which rsync matches at
  any depth, not the top-level docs/_internal/ that the comment describes. It is
  now `/_internal`, anchored to the top of the transfer, so it states what it
  means and it cannot surprise a later author who adds a published path that
  contains that word.
- docusaurus.config.ts: `path: v === LATEST_VERSION ? '' : v` reproduces the
  default that Docusaurus already applies to lastVersion. A comment now records
  that the explicit form is a choice, so nobody removes it as a redundancy.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: IBRAHIM IBRAHIM <66755652+Ibrahim2595@users.noreply.github.com>

---------

Signed-off-by: IBRAHIM IBRAHIM <66755652+Ibrahim2595@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants