diff --git a/.ai/rules/astro-starlight-site.md b/.ai/rules/astro-starlight-site.md new file mode 100644 index 00000000..aa654cdc --- /dev/null +++ b/.ai/rules/astro-starlight-site.md @@ -0,0 +1,65 @@ +--- +applyTo: "web/**/*.{js,mjs,ts,astro,json,md,mdx}" +paths: + - "web/**" +--- + +# Astro/Starlight exact public-surface rules + +The deployed cratis.io site is an exact projection, not a broad documentation +crawl. + +## Publication source + +- `web/public-surface.json` owns the admitted route, source repository/path, + reviewed revision, SHA-256, claim IDs, sitemap flag, and exact static files. +- `web/scripts/sync-public-content.mjs` validates and materializes only that + manifest. Unknown routes, source/hash drift, Draft content, CLM-010 matrix + wording, symlink escapes, search/machine output, and policy differences fail. +- `web/src/content/docs/`, `web/src/generated/`, and `web/.public-approved/` are + disposable outputs. Never edit or commit them. +- Site-owned source lives in `web/src/public-pages/`; product source stays in the + owning product repository. +- `npm run sync:authoring` is broad, nondeployable authoring only. + +## Native Markdown and MDX contract + +Exact-production source is copied byte-for-byte. It does not receive the legacy +DocFX conversion pipeline. + +Every admitted page must therefore: + +- use Starlight frontmatter with at least `title` and a bounded `description`; +- omit a body H1 because Starlight renders the frontmatter title; +- start body sections at H2; +- use native Starlight aside syntax and root-relative trailing-slash links; +- use `.mdx` when importing Starlight or custom components; +- avoid DocFX alerts, xrefs, includes, `.md` URL suffixes, and relative product + assets; and +- keep every component-emitted link inside the manifest route set. + +## Product landing pages + +Product overviews use the tour pattern where it helps readers: + +- `TopicHero` for exact product identity and one bounded reader job; +- Starlight `CardGrid`, `Card`, `LinkCard`, and `Steps`; +- `SimpleCard` only with page-supplied wording and admitted links; +- `FullStackTabs` only for source-verified paired examples. + +Do not use `RotatingHero`, `StackJourney`, `StackDiagram`, or Storybook embeds in +the current eight-route manifest. They own excluded claims/routes/artifacts. + +## Build and deployment + +- `npm ci && npm run check` is the authoritative local and CI gate. +- Astro/Starlight is the authoritative MDX parser and component resolver. +- Rendered-link validation catches links emitted from MDX components. +- Pagefind, llms files, page actions, raw Markdown mirrors, Storybooks, and API + sites remain disabled until separately admitted. +- Pull requests validate reviewed product revisions with read-only credentials. +- Main deployment checks product `main` bytes and fails on hash drift. +- Pages/OIDC permissions exist only in the main-only deploy job. + +Never weaken a route, claim, hash, artifact, or deployment check merely to make a +build green. diff --git a/.ai/rules/documentation-rendering-and-qa.md b/.ai/rules/documentation-rendering-and-qa.md new file mode 100644 index 00000000..85301aae --- /dev/null +++ b/.ai/rules/documentation-rendering-and-qa.md @@ -0,0 +1,60 @@ +--- +applyTo: "web/**/*.{astro,css,md,mdx,js,mjs,ts}" +paths: + - "web/**" +--- + +# Documentation rendering and visual QA + +A successful build proves syntax and route integrity, not a professional reader +experience. Review rendered output for every changed admitted route. + +## Required rendered checks + +1. Run the exact production build: + + ```bash + cd web + npm ci + npm run check + ``` + +2. Serve the built site with `npm run preview`. +3. Capture every admitted route in light and dark mode. +4. Capture `/`, each product landing, and `/404.html` at a mobile width. +5. Verify keyboard traversal, visible focus, heading order, descriptive links, + table/code overflow, diagram readability, and no image-dependent meaning. +6. Verify reduced-motion mode and no carousel/ambient motion requirement. +7. Check first load for font/image/layout shift. + +Use `web/scripts/screenshot.mjs` for reproducible screenshots when available. +Screenshots are local review evidence and are not committed unless their exact +public asset/provenance path is separately admitted. + +## Preserve current rendering safeguards + +- Keep the custom `Head.astro` font preload and `font-display: optional` behavior. +- Keep Mermaid build-time rendering and `autoTheme: false`; light/dark colors are + handled by CSS variables. +- Keep the theme-adaptive Cratis marks and an empty alt only when the mark is + decorative and equivalent text is present. +- Keep product pages useful without JavaScript. + +## MDX component review + +- `TopicHero` and `SimpleCard` are render-only and safe when all text/links come + from the page. +- Starlight `Card`, `CardGrid`, `LinkCard`, `Steps`, `Tabs`, and `Aside` are + preferred for native behavior. +- Validate icon names during Astro build. +- Inspect component output in final HTML; source-only Markdown link scans are not + sufficient. +- Do not hide claim text, links, or product relationships inside imported + components that are not included in the manifest review. + +## Failure handling + +Block the candidate on broken layout, unreadable contrast, inaccessible focus, +mobile overflow, missing content without JavaScript, diagram failure, unexpected +route/link output, or material layout shift. Fix the source or component; do not +waive the public-surface gate. diff --git a/.github/workflows/docs-site.yml b/.github/workflows/docs-site.yml index d20e993f..cad2247d 100644 --- a/.github/workflows/docs-site.yml +++ b/.github/workflows/docs-site.yml @@ -1,310 +1,121 @@ -# Builds and deploys the Astro Starlight documentation site (Documentation/web). -# -# Content lives in each product repo's `Documentation/` folder. Chronicle client -# docs and snippets live in each client repo's `Documentation/` folder. This -# workflow checks each source repo out as a sibling of this repo, matching the -# local dev layout the converter expects (scripts/sync-content.mjs). -# It uses `docs-overhaul` for docs-overhaul validation and `main` for production -# builds and product-repo dispatches. -# -# The build runs on both `docs-overhaul` (validation) and `main`; product repos -# dispatch `build-docs` after docs changes on their `main` branches. The deploy job -# runs ONLY on `main`, so a docs-overhaul push validates the build without publishing. -# -# PREREQUISITES (one-time, manual): -# 1. Enable GitHub Pages for this repo with "GitHub Actions" as the source. -# 2. The checked-out product repos are public. If any become private, add a repo/org -# secret `DOCS_CHECKOUT_TOKEN`; the checkout steps fall back to `github.token`. -# 3. If serving under a sub-path (e.g. cratis.io/docs), set `base: '/docs'` in astro.config.mjs. - name: Documentation site on: + pull_request: + branches: [main] push: - branches: [docs-overhaul, main] + branches: [main] workflow_dispatch: repository_dispatch: types: [build-docs] permissions: contents: read - pages: write - id-token: write concurrency: - group: docs-site-${{ github.ref_name }} + group: docs-site-${{ github.event.pull_request.number || github.ref_name }} cancel-in-progress: true -# Product repos are checked out at docs-overhaul only for docs-overhaul validation. -# Main pushes, manual runs from main, and repository_dispatch runs use main. -env: - DOCS_REF: ${{ github.ref_name == 'docs-overhaul' && 'docs-overhaul' || 'main' }} - ELIXIR_VERSION: "1.19.5" - OTP_VERSION: "28.5" - jobs: build: runs-on: ubuntu-latest timeout-minutes: 30 steps: - name: Checkout Documentation - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: path: Documentation + persist-credentials: false - - name: Checkout Samples - uses: actions/checkout@v4 - with: - repository: Cratis/Samples - ref: main - token: ${{ secrets.DOCS_CHECKOUT_TOKEN || github.token }} - path: Samples + - name: Resolve reviewed product revisions + id: revisions + working-directory: Documentation/web + env: + VALIDATE_REVIEWED_REVISIONS: ${{ github.event_name == 'pull_request' }} + run: | + if [ "$VALIDATE_REVIEWED_REVISIONS" != "true" ]; then + { + for name in chronicle arc components cli; do echo "$name=main"; done + } >> "$GITHUB_OUTPUT" + exit 0 + fi + + resolve() { + jq -er --arg repository "$1" \ + '[.routes[].source | select(.repository == $repository) | .revision] | unique | if length == 1 then .[0] else error("expected one revision") end' \ + public-surface.json + } + + { + echo "chronicle=$(resolve Chronicle)" + echo "arc=$(resolve Arc)" + echo "components=$(resolve Components)" + echo "cli=$(resolve cli)" + } >> "$GITHUB_OUTPUT" - name: Checkout Chronicle - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: repository: Cratis/Chronicle - ref: ${{ env.DOCS_REF }} - token: ${{ secrets.DOCS_CHECKOUT_TOKEN || github.token }} + ref: ${{ steps.revisions.outputs.chronicle }} path: Chronicle - - - name: Checkout Chronicle.Kotlin client docs - uses: actions/checkout@v4 - with: - repository: Cratis/Chronicle.Kotlin - ref: main - token: ${{ secrets.DOCS_CHECKOUT_TOKEN || github.token }} - path: Chronicle.Kotlin - - - name: Checkout Chronicle.Elixir client docs - uses: actions/checkout@v4 - with: - repository: Cratis/Chronicle.Elixir - ref: main - token: ${{ secrets.DOCS_CHECKOUT_TOKEN || github.token }} - path: Chronicle.Elixir - - - name: Checkout Chronicle.TypeScript client docs - uses: actions/checkout@v4 - with: - repository: Cratis/Chronicle.TypeScript - ref: main - token: ${{ secrets.DOCS_CHECKOUT_TOKEN || github.token }} - path: Chronicle.TypeScript - - - name: Checkout Chronicle.Mcp - uses: actions/checkout@v4 - with: - repository: Cratis/Chronicle.Mcp - ref: main - token: ${{ secrets.DOCS_CHECKOUT_TOKEN || github.token }} - path: Chronicle.Mcp + persist-credentials: false - name: Checkout Arc - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: repository: Cratis/Arc - ref: ${{ env.DOCS_REF }} - token: ${{ secrets.DOCS_CHECKOUT_TOKEN || github.token }} + ref: ${{ steps.revisions.outputs.arc }} path: Arc + persist-credentials: false - name: Checkout Components - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: repository: Cratis/Components - ref: ${{ env.DOCS_REF }} - token: ${{ secrets.DOCS_CHECKOUT_TOKEN || github.token }} + ref: ${{ steps.revisions.outputs.components }} path: Components + persist-credentials: false - - name: Checkout AuthProxy - uses: actions/checkout@v4 - with: - repository: Cratis/AuthProxy - ref: ${{ env.DOCS_REF }} - token: ${{ secrets.DOCS_CHECKOUT_TOKEN || github.token }} - path: AuthProxy - - - name: Checkout Fundamentals - uses: actions/checkout@v4 - with: - repository: Cratis/Fundamentals - ref: ${{ env.DOCS_REF }} - token: ${{ secrets.DOCS_CHECKOUT_TOKEN || github.token }} - path: Fundamentals - - - name: Checkout cli - uses: actions/checkout@v4 + - name: Checkout CLI + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: repository: Cratis/cli - ref: ${{ env.DOCS_REF }} - token: ${{ secrets.DOCS_CHECKOUT_TOKEN || github.token }} + ref: ${{ steps.revisions.outputs.cli }} path: cli + persist-credentials: false - - name: Checkout .github (Contributing) - uses: actions/checkout@v4 - with: - repository: Cratis/.github - ref: ${{ env.DOCS_REF }} - token: ${{ secrets.DOCS_CHECKOUT_TOKEN || github.token }} - path: .github - - - name: Checkout Architecture - uses: actions/checkout@v4 - with: - repository: Cratis/Architecture - ref: main - token: ${{ secrets.DOCS_CHECKOUT_TOKEN || github.token }} - path: Architecture - - - name: Checkout Screenplay - uses: actions/checkout@v4 - with: - repository: Cratis/Screenplay - ref: main - token: ${{ secrets.DOCS_CHECKOUT_TOKEN || github.token }} - path: Screenplay - - - name: Checkout Stage - uses: actions/checkout@v4 - with: - repository: Cratis/Stage - ref: main - token: ${{ secrets.DOCS_CHECKOUT_TOKEN || github.token }} - path: Stage - - - name: Checkout Screenplay.Generation - uses: actions/checkout@v4 - with: - repository: Cratis/Screenplay.Generation - ref: main - token: ${{ secrets.DOCS_CHECKOUT_TOKEN || github.token }} - path: Screenplay.Generation - - - name: Checkout Screenplay.CritterStack - uses: actions/checkout@v4 - with: - repository: Cratis/Screenplay.CritterStack - ref: main - token: ${{ secrets.DOCS_CHECKOUT_TOKEN || github.token }} - path: Screenplay.CritterStack - - - name: Checkout Prologue - uses: actions/checkout@v4 + - name: Setup Node + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: - repository: Cratis/Prologue - ref: main - token: ${{ secrets.DOCS_CHECKOUT_TOKEN || github.token }} - path: Prologue - - - name: Checkout Prompter - uses: actions/checkout@v4 - with: - repository: Cratis/Prompter - ref: main - token: ${{ secrets.DOCS_CHECKOUT_TOKEN || github.token }} - path: Prompter - - - uses: actions/setup-node@v4 - with: - node-version: 23 # Components (Storybook build) requires node >=23 + node-version: 23 - name: Install dependencies working-directory: Documentation/web - run: npm ci || npm install - - - name: Setup JDK - uses: actions/setup-java@v4 - with: - java-version: '17' - distribution: 'temurin' - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 - with: - gradle-version: '8.13' - - - name: Setup Elixir and Erlang - uses: erlef/setup-beam@v1 - with: - elixir-version: ${{ env.ELIXIR_VERSION }} - otp-version: ${{ env.OTP_VERSION }} - - - name: Install Chronicle TypeScript dependencies - working-directory: Chronicle.TypeScript - run: | - corepack enable - yarn install --immutable - - - name: Install Chronicle Elixir dependencies - working-directory: Chronicle.Elixir/Source/chronicle - run: | - mix local.hex --force - mix local.rebar --force - mix deps.get - - - name: Build Components Storybook - working-directory: Components - run: | - corepack enable - if [ -f yarn.lock ]; then - yarn install --immutable - else - yarn install - fi - (cd Source && ../node_modules/.bin/storybook build -o ../../Documentation/web/public/storybook) - - - name: Build Arc React Storybook - working-directory: Arc/Source/JavaScript - run: | - corepack enable - if [ -f yarn.lock ]; then - yarn install --immutable - else - yarn install - fi - yarn workspace @cratis/arc.react exec storybook build -o ../../../../Documentation/web/public/storybook-arc - - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: '10.0.x' - - - name: Generate API reference (DocFX + TypeDoc) - working-directory: Documentation/web - run: | - dotnet tool install -g docfx || dotnet tool update -g docfx - npm run build:api - - - name: Lint docs - working-directory: Documentation/web - run: npm run sync && npm run lint:docs - - - name: Check Chronicle client docs - working-directory: Documentation/web - run: npm run chronicle-client-docs:check:ci - - - name: Build site - working-directory: Documentation/web - run: npm run build + run: npm ci - - name: Check internal links + - name: Validate and build the exact public surface working-directory: Documentation/web - run: npm run check:links + run: npm run check - name: Upload Pages artifact - uses: actions/upload-pages-artifact@v3 + if: ${{ github.event_name != 'pull_request' }} + uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3 with: path: Documentation/web/dist deploy: needs: build - # Publish to Pages only from main — docs-overhaul runs are build-only validation. - if: ${{ github.ref_name == 'main' }} + if: ${{ github.event_name != 'pull_request' && github.ref_name == 'main' }} runs-on: ubuntu-latest timeout-minutes: 30 + permissions: + contents: read + pages: write + id-token: write environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} steps: - id: deployment - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4 diff --git a/.gitignore b/.gitignore index 264c357a..ae931df3 100644 --- a/.gitignore +++ b/.gitignore @@ -283,6 +283,7 @@ __pycache__/ package-json.lock package-lock.json +!web/package-lock.json dist **/node_modules/ *.tsbuildinfo @@ -329,4 +330,10 @@ snippets.json # Storybook build output **/storybook-static/ -web/src/content/docs/architecture \ No newline at end of file + +# Exact public-surface projections (generated by sync-public-content.mjs) +web/src/content/docs/ +web/src/generated/topics.json +web/src/generated/public-routes.json +web/.public-approved/ +web/node_modules \ No newline at end of file diff --git a/archive/DOCS-AUDIT-2026-07.md b/archive/DOCS-AUDIT-2026-07.md deleted file mode 100644 index 22156226..00000000 --- a/archive/DOCS-AUDIT-2026-07.md +++ /dev/null @@ -1,172 +0,0 @@ -> [!NOTE] -> **Historical record — written 2026-07-16. Not a live plan.** -> -> This audit is preserved here as a **record of what the documentation looked like on -> 2026-07-16**, not as a backlog anyone is currently working. It was never tracked in git -> until this commit and sat untracked in a working copy for a month. -> -> **Its findings are largely unaddressed.** A follow-up sweep re-checked the audit's -> concrete claims and found roughly **12 of 49 checks** now passing — and of those, close to -> **0% are attributable to the audit itself**; they were fixed by unrelated work that -> happened to touch the same pages. A spot-check on 2026-08-19 re-verified five of the P0 -> findings against the relevant repositories' `main` branches and found **all five still -> open**: Arc's `using OneOf;` in `Documentation/backend/commands/model-bound/index.md`, the -> two "will be documented here" placeholders in `Documentation/backend/proxy-generation.md`, -> the `beforeExecute` (vs `onBeforeExecute`) prop in `form-lifecycle.md`, the "TypeScript 6" -> line in `web/src/content/docs/compatibility.mdx`, and the stale "Latest release digest" -> card in `web/src/content/docs/whats-new.mdx`. -> -> **Treat every specific claim below as dated.** Line numbers, page counts, percentages, and -> file paths were accurate on 2026-07-16 and have drifted since. Re-verify anything before -> acting on it. The audit's *method* and *framing* have aged better than its *citations*. -> -> Kept because the analysis is substantive and re-deriving it would cost more than reading -> it — not because it is current. - -# Cratis Documentation Audit — 2026-07-16 - -A full content, structure, and site audit of the Cratis documentation (the `Cratis/Documentation` Astro Starlight site aggregating Chronicle, Arc, Components, CLI, Fundamentals, Architecture, Screenplay, Prompter, AuthProxy, Contributing) and the live **cratis.io**. - -**Method.** Fresh `npm run build` + every QA gate; first-hand link/frontmatter/diagram/heading censuses across all ~873 rendered pages; live-site + external-link probes; design/AI-export review; and five parallel deep-dive audits (one per product area) whose every code claim was verified against product `Source/`. Environment note: product siblings were on feature branches, so local content ≈ but is not identical to production `main`. - ---- - -## Executive summary - -**Verdict: a strong, professionally-presented documentation set with an excellent flagship layer — held back by a small number of concrete correctness bugs, one pervasive metadata gap, and structural/IA debt in the machine-converted reference tree.** This is a "raise a good site to a great one" list, not a rescue. - -The site is genuinely good where the team invested by hand: the front door, the per-product Overview/"Understanding" pages, the tutorials, and the scenarios read like a real teacher's tour (pain→relief, why-before-how, diagrams, synced C#↔TypeScript). The presentation layer (884-line brand CSS, rich custom components) is well above a default Starlight skin. Build passes; internal-link hygiene is excellent (1 genuinely broken internal link across 339 Chronicle pages). - -The weaknesses cluster into five themes: - -1. **Copy-paste code bugs** — a few widely-repeated examples don't compile / use removed or invented APIs. Highest severity because readers paste them verbatim. -2. **Systemic metadata gap** — 86% of pages have no `description` frontmatter (SEO, social cards, and the `llms.txt` AI export all read it). -3. **A two-tier quality split** — the hand-authored narrative layer is excellent; the bulk-converted DocFX reference tree is passive-voiced, diagram-less, description-less, and carries structural collisions. -4. **Structure & IA debt** — file-vs-folder URL collisions, orphaned sections, CI artifacts shipped as user docs, and an overloaded top-level nav topic that buries whole products. -5. **The full-stack differentiator is under-shown** — `` (synced C#↔TS), the thing that most distinguishes Cratis, appears on a handful of pages and is absent from the reference where it matters most. - -### Scorecard - -| Area | Pages | Health | One-line | -|---|---|---|---| -| Front door / homepage | — | ★★★★★ | Strong hero, clear value prop, copy-pasteable quickstart, good CTAs. | -| Design / presentation | — | ★★★★★ | Hand-crafted brand theme + components; a real strength to preserve. | -| Chronicle | 339 | ★★★★ | Excellent where invested; CI artifacts leak, some contradictions, 89% no description. | -| Arc | 266 | ★★★½ | Superb narrative tier; reference tier has 4 URL collisions + 3 wrong code examples. | -| Components | 91 | ★★★½ | Great recipes; ~75 auto-ref pages weaker; removed `primereact/column` import ×9. | -| CLI | 31 | ★★★½ | Strong content, but `scenarios/` + reference landing orphaned from nav. | -| Prompter | 15 | ★★★★★ | Mature, tour-voiced, ready to surface. | -| AuthProxy | 6 | ★★★★★ | Hand-authored, diagrammed, honest security caveats. | -| Screenplay | 19 | ★★★★ | Substantive; "run it live" promise outruns shipped tooling — frame as Preview. | -| Fundamentals | 45 | ★★★ | Modernized landings only; deep `.md` are reference-dumps, ~1 diagram, no descriptions. | -| Architecture | 29 | ★★★ | Correct terse Roslyn-rule reference; thin landing, duplicate index tables. | -| Contributing | 18 | ★★★ | Solid but older; `building.md` omits frontend; release-digests orphaned. | -| IA / navigation | — | ★★½ | Overview topic overloaded (~23 entries); products buried; two "Scenarios". | -| QA tooling | — | ★★★ | Good gates, but 2 of 6 silently no-op locally; `check` needs API+Storybook builds. | - ---- - -## Priority 0 — Correctness & things users hit (fix first) - -### P0.1 — Broken / invented copy-paste code -- **[Components · High] Removed `primereact/column` import taught in 9 places.** `Column` is imported from `primereact/column`, but `Components/Source/DataTables/Column.tsx` is the Cratis-owned typed replacement (its own doc-comment says it replaces the *removed* `primereact/column`) and is exported from the `@cratis/components/DataTables` barrel. Readers get a broken import. Locations: `components/displaying-data.md:17`, `components/list-screen-with-actions.md:19`, `components/tutorial/list-it.mdx:18`, `components/tutorial/list-and-detail.mdx:33`, `components/DataTables/data-table-for-query.md:24`, `components/DataTables/data-table-for-observable-query.md:24`, `components/DataPage/index.md:26` & `:57`, `components/DataPage/menu-items.md:13`. **Fix:** `import { Column } from '@cratis/components/DataTables'`. -- **[Arc · High] Invented `CommandResult` API.** `arc/frontend/react/command-form/validation.md` (~392–439) uses `result.hasErrors('email')` / `result.getErrorsFor('email')` and an `errors` map. Verified against `Arc/Source/JavaScript/.../ICommandResult.ts`: only `isSuccess/isAuthorized/isValid/hasExceptions/validationResults/response` exist; `hasErrors`/`getErrorsFor` have zero project hits. **Fix:** use `validationResults` (field errors come from the form context's `getFieldError`). -- **[Arc · High] Wrong form-lifecycle prop.** `arc/frontend/react/command-form/form-lifecycle.md` (~158–171) documents `beforeExecute` returning `Promise` to cancel submission. The real prop is `onBeforeExecute` (a value transform, `CommandForm.tsx:313`), not a boolean gate — and `command-form/index.md:69` already lists it correctly. Same page (`:12`) uses the wrong import `@cratis/arc/commands` (core) for a React component → should be `@cratis/arc.react/commands`. -- **[Components · Medium] `column-configuration.md` documents PrimeReact's `Column` surface** (`filterMatchMode`, `filterElement`, `exportable`, `frozen`, `headerStyle`) but shipped `ColumnProps` is a different curated surface (`dataType`, `showFilterMatchModes`, typed `body`). Rewrite against the real props. -- **[Components · Medium] `Dropdown/index.md:181-192`** uses PrimeReact `` (unimported) contradicting the Cratis `Dialog` (`onConfirm/onCancel/onClose`). Use the Cratis dialog. -- **[Arc · Low] `using OneOf;` should be `using Cratis.Monads;`** in `arc/backend/commands/model-bound/index.md:38,65,185` — the `Result` guards won't compile as written. - -### P0.2 — Factual contradictions & wrong statements -- **[Chronicle · High] Event Revision contradiction.** `chronicle/concepts/event-sequence.md:48-50` says revisions are "not fully implemented yet, there is no API surface"; `chronicle/events/revision.md` documents a working Workbench procedure for the same feature. Reconcile to one truth. -- **[Chronicle · High] Three conflicting "three projection approaches".** `projections/architecture.mdx:9` (PDL/Model-Bound/Declarative) vs `projections/index.md:28` (Model-bound/Declarative/Reducer) vs `projections/choosing-a-read-model-style.mdx` (Model-bound/Declarative/Reducer). Pick one canonical framing; surface PDL (currently orphaned from the landing). -- **[Chronicle · High] `.AutoMap()` taught against the project's own rule + analyzer.** ~10 declarative pages (`projections/declarative/{event-context,from-event-sequence,functions,joins,not-rewindable,passive,remove-with-join,set-properties,index}.mdx`, `model-bound/index.mdx`) call `.AutoMap()` as routine boilerplate, while `projections/declarative/simple-projection.mdx:83` correctly says never to. Remove the routine calls. -- **[Chronicle · Medium] Wrong glossary term.** `chronicle/concepts/glossary.md:85` defines **Subject** as "an observable stream… behind reactive queries" — but the compliance docs and the site glossary define Subject as the PII/GDPR identity. Correct it. -- **[Chronicle · Medium] MongoDB-only claim.** `chronicle/concepts/event-store.md:11-13` presents MongoDB as the only backend, contradicting `index.mdx` + `hosting/configuration/storage.md` (Mongo/Postgres/SQL Server/SQLite). -- **[Site · Medium] `compatibility.mdx:26` says "TypeScript 6"** — Arc ships `typescript 7.0.2` (verified `Arc/package.json`; Fundamentals/Components on 6.0.3). Node ≥23 and Yarn 4.5.3 on that page are correct — leave them. -- **[Site · Medium] `whats-new.mdx` stale.** The "Latest release digest" card points to `2026-05-25-to-2026-06-01`, the 2nd-oldest of 6 digests (newest is `2026-06-22-to-2026-06-29`). -- **[Site · Medium] Studio described in present tense** (`why-cratis.mdx:58`, `cratis-stack.mdx:19`) though it's badged "Soon". Use future framing to match `studio.mdx`'s own honesty. - -### P0.3 — Structural collisions, orphans, and shipped placeholders -- **[Arc · High] Four file-vs-folder URL collisions.** A `foo.md` sibling to a `foo/` folder makes the sync demote the folder's `index.md` to `overview.md`, leaving the flat file as the landing: `backend/mongodb.md` (tells readers to "visit /arc/backend/mongodb/" — its own URL; real content orphaned at `/mongodb/overview/`), `backend/proxy-generation/configuration.md` (self-referential "moved" stub), `backend/chronicle/commands.md` ("moved" banner atop 150 lines duplicating `backend/chronicle/commands/`), and `frontend/core/queries.md` (167 lines) vs `frontend/core/queries/overview.md` (22 lines) — two pages titled "Queries", the stale controller-based one is what everything links to. Fix: one shape per section (real `index.md`, delete the sibling). -- **[Chronicle · High] CI artifacts shipped as user docs.** `chronicle/statistics/` embeds a coverage dashboard via raw `