Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .agents/skills/audit-catalogue-projects/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,10 @@ Related: `project-manifest-reference` (fields and vocabularies), `docs-aggregati
cache).
- Exactly one `primary` when a project has multiple packages.
- `targetFrameworks` match the package's actual TFMs (`netstandard2.0` for generators/analyzers is
normal).
normal). `just check-projects` reports a mismatch as an advisory observation: project-level
frameworks against the union of the runtime packages' published TFMs, package-level frameworks
against that package's own. `netstandard*` is treated as an analyzer/generator target, not a
consumer framework.
- `install` is set only when the package is not a plain NuGet reference: `msbuild-sdk` for
`Purview.BuildSdk`, `dotnet-tool` for `Purview.Build`.

Expand Down
7 changes: 5 additions & 2 deletions .agents/skills/project-manifest-reference/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,9 @@ Adding a value to any of these lists is a schema change and requires an ADR. `ex
| `order` | no | Default `1000`; projects are sorted ascending; keep values unique |
| `docs` | no | See below |
| `install` | no | Default `nuget` |
| `targetFrameworks` | no | e.g. `net8.0`, `net9.0`, `net10.0`, `netstandard2.0` |
| `targetFrameworks` | no | e.g. `net8.0`, `net9.0`, `net10.0`, `netstandard2.0`; `just check-projects` reports (advisory) when it does not match the union of the runtime packages' published NuGet TFMs |
| `packages` | no | `{ id, description?, primary?, targetFrameworks? }[]`; defaults to `[]` |
| `assets` | no | `{ path, output, description? }[]`; repository files mirrored into `public/` at build time (`path` is repo-relative, `output` is site-relative); defaults to `[]` |
| `related` | no | Known project ids; rendered in the project page aside |
| `useCases` | no | Default `[]`; at least one required for non-archived projects |
| `acknowledgments` | no | `{ name, url, description? }[]`; upstream work the project credits |
Expand Down Expand Up @@ -81,7 +82,9 @@ Adding a value to any of these lists is a schema change and requires an ADR. `ex
3. `related`, `supersedes`, and `supersededBy` must all reference existing project ids.
4. A NuGet package id may be declared by **exactly one** project.
5. `experimental: true` is rejected when `status` is `archived` (schema refinement).
6. The returned list is sorted by `order` ascending.
6. An asset `output` path may be declared by **exactly one** project, must be relative, and must
not contain a `..` segment.
7. The returned list is sorted by `order` ascending.

## Defaults applied by the loader

Expand Down
25 changes: 24 additions & 1 deletion .agents/skills/site-validation-loop/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ tags:
| Catalogue | `just check-projects` | Catalogue invariants (see below) |
| Build | `just build` (runs live data sync first) | Astro/Starlight build, sidebar/llms plugin wiring |
| Links | `just check-links` | Broken internal links **and missing anchors** across `dist/**/*.html` |
| Generated output | `just check-generated` | Docs cache/mirror agreement, release cache shape, `llms*.txt`, sitemap, robots, no secrets/local paths |
| Generated output | `just check-generated` | Docs cache/mirror agreement, release cache shape, mirrored project assets exist and are valid JSON, `llms*.txt`, sitemap, robots, no secrets/local paths |
| Dist tests | `just test:dist` | Per-project LLM bundles, rendered project/use-case surfaces, footer version, SEO outputs |

## The catalogue guard (`just check-projects`)
Expand All @@ -49,8 +49,26 @@ deterministic). It fails the build on:
`discussions: true` without repository discussions;
- `externalProjects` pointing at a `purview-dev` repository.

Beyond those blockers, the guard prints **advisory observations** (they never fail the build) when a
project disagrees with the versions and frameworks its packages have published:

- a `preview` project whose packages already publish a stable NuGet version (unless `experimental`);
- a NuGet package that is deprecated or unlisted;
- packages that trail the project's headline version;
- `targetFrameworks` that do not match the packages' NuGet nuspec metadata. Project-level frameworks
are compared with the union of the **runtime** packages' frameworks; package-level frameworks are
compared with that package's own. `netstandard*` is treated as an analyzer/generator build target
(never a consumer framework), and `install: msbuild-sdk`/`dotnet-tool` projects and the `msbuild`
sentinel are skipped.

Run it alone while iterating: `just check-projects`.

Apply the machine-applicable observations (missing/mismatched `targetFrameworks`, `preview` →
`stable` when a stable package exists) with `just fix-projects`; it is a dry run by default and only
edits the records with `--write`. It rewrites the affected `targetFrameworks` lists to exactly the
expected set (so it also removes frameworks a package no longer targets), but never touches blockers
or judgement calls such as replacing a deprecated package.

## Data-sync modes

`DATA_MODE` (`src/.env.example`) controls how docs/release data is obtained:
Expand All @@ -60,6 +78,11 @@ Run it alone while iterating: `just check-projects`.
- `cache` — only use the existing cache (fails if missing).
- `fixture` — only use `src/fixtures/**` (fully offline, deterministic).

The same mode governs mirrored **project assets** (`assets:` in a record): `just data-sync` fetches
each declared repository file with the docs aggregator's `fetchRawFile`, writes it to `public/`, and
caches it under `.cache/assets/`. A declared asset that cannot be resolved fails the sync, so a
missing schema never silently ships a broken URL.

`DATA_FALLBACK_TO_FIXTURES=false` makes `auto` fail loudly instead of silently using fixtures. Set
`GITHUB_TOKEN` (or `gh auth token`) to avoid unauthenticated rate limits.

Expand Down
5 changes: 4 additions & 1 deletion .config/lefthook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ pre-commit:
oxfmt:
root: src
glob: '*.{ts,tsx,css,md,mdx,json,yml,yaml,toml}'
run: bunx oxfmt {staged_files}
# `--no-error-on-unmatched-pattern` keeps the hook green when the staged
# files are all covered by oxfmt's `ignorePatterns` (e.g. a commit that
# only touches `fixtures/**`). Genuine formatting issues still fail.
run: bunx oxfmt --no-error-on-unmatched-pattern {staged_files}
oxlint:
root: src
glob: '*.{ts,tsx,js,jsx,astro}'
Expand Down
3 changes: 3 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ package is `src/`.
- Edit the catalogue under `src/src/data/` only (one file per project, plus `external-projects.yml`), and keep every invariant listed in
`AGENTS.md` (unique ids/orders/packages, `name` slugifying to `id` for documented projects, at
least one use case per non-archived project, `code` paired with `language`, resolvable `docsPage`).
- Keep declared `status` and `targetFrameworks` honest: `just check-projects` prints advisory
observations when they disagree with the packages' published NuGet versions and frameworks. Apply
the machine-applicable ones with `just fix-projects` (dry run; pass `--write` to edit).
- Keep documentation where it lives (the product repository). This site aggregates it at build time.
- Use Conventional Commits and keep changes small and reviewable.

Expand Down
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,9 @@ src/public/icon-192.png
src/public/icon-512.png
src/public/og/

# Mirrored project assets (regenerated by `just data-sync`)
src/public/schemas/

### Go ###
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
Expand Down Expand Up @@ -674,10 +677,16 @@ sketch
# The generic template ignores `[Rr]elease*/` and `dist` as build output, but
# the site uses those names for source: the releases catalogue page, release
# transforms, committed release fixtures, and the built-output test suite.
# Likewise `[Bb]uild/` would ignore the committed asset fixture for the
# `purview-dev/build` repository under `fixtures/assets/build/`.
!src/fixtures/github/releases/
!src/fixtures/github/releases/**
!src/fixtures/releases/
!src/fixtures/releases/**
!src/fixtures/assets/
!src/fixtures/assets/**
!src/fixtures/assets/build/
!src/fixtures/assets/build/**
!src/src/lib/releases/
!src/src/lib/releases/**
!src/src/pages/releases/
Expand Down
17 changes: 14 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,16 @@ from the repository root and delegated to the package.
on `astro check` + oxlint.
- **Task runner:** Just (`justfile`; switches to pwsh on Windows).
- **All external data is fetched at build time**, never by the visitor's browser: GitHub/NuGet
release data and the documentation mirror, cached under `src/.cache/` with committed fixtures as
the offline fallback.
release data, the documentation mirror, and any `assets:` a project mirrors into `public/`, cached
under `src/.cache/` with committed fixtures as the offline fallback.

### Generated outputs — never edit by hand

| Path | What it is | Regenerate with |
| --- | --- | --- |
| `src/src/content/docs/**` | Aggregated documentation mirror (gitignored) | `just data-sync` |
| `src/.cache/docs`, `src/.cache/releases` | Typed docs/release caches (gitignored) | `just data-sync` / `just fetch-releases` |
| `src/public/schemas/**` | Mirrored project assets declared in `assets:` (gitignored) | `just data-sync` |
| `src/dist/**` | Production build output (gitignored) | `just build` |

### Authoritative validation
Expand All @@ -47,7 +48,9 @@ just validate
runs format-check → lint → typecheck → unit tests → asset checks → catalogue checks → build →
link crawl → generated-output checks → built-output tests. It is the same pipeline CI uses
(`purview-build.json` → `bun run ci:build`), so a green `just validate` is the definition of "safe to
merge". `just check-projects` is part of that chain and fails the build on catalogue drift.
merge". `just check-projects` is part of that chain and fails the build on catalogue drift. It also
prints advisory observations (which never fail the build) when a project's declared `status` or
`targetFrameworks` disagree with the versions and frameworks its packages have actually published.

## Ecosystem model — what "a project" means here

Expand Down Expand Up @@ -81,6 +84,13 @@ merge". `just check-projects` is part of that chain and fails the build on catal
- `related`, `supersedes`, `supersededBy` must reference known ids.
- `status` must match reality: an archived repository is `archived`; prerelease-only tooling is
`preview`; a project with a stable release is `stable`.
- Declared versions and frameworks must agree with what the packages publish: a stable NuGet
version on a `preview` project, a deprecated or unlisted package, packages that trail the family
version, and a `targetFrameworks` set (project- or package-level) that does not match the
packages' NuGet metadata are reported as advisory observations by `just check-projects`. They
never fail the build, but they are catalogue drift and should be fixed or explicitly accepted.
Run `just fix-projects` to apply the guard's machine-applicable fixes (a dry run by default;
pass `--write` to edit the records).
- `experimental: true` marks a project whose API and packaging may change without notice
(ADR 0004). It is orthogonal to `status` — which stays the release channel — it is invalid on an
`archived` project, and it never hides a project: it adds a warning badge and a notice to the
Expand Down Expand Up @@ -120,6 +130,7 @@ Do not assume this file contains everything; consult `.agents/` while planning.
| Manifest schema / loader | `src/src/lib/manifest/{schema,load}.ts` |
| Docs aggregation | `src/src/lib/docs/aggregate.ts` (+ `frontmatter`, `links`, `sidebar`, `staleness`) |
| Release data | `src/src/lib/releases/*`, `src/scripts/fetch-releases.ts` |
| Mirrored project assets | `src/scripts/sync-assets.ts` (`assets:` in the manifest) |
| Pages | `src/src/pages/{index,about,use-cases,docs,projects,releases}/` |
| Validation | `justfile`, `src/scripts/{check-links,check-generated,check-assets,check-projects}.ts` |
| Architecture decisions | `docs/decisions/*.md` |
4 changes: 4 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ check-generated:
check-projects:
bun run check:projects

# Apply the guard's auto-fixes to the project records (dry run; pass --write to apply).
fix-projects *ARGS:
bun run fix:projects {{ARGS}}

# Validate the generated discovery artifacts (sitemaps, robots, llms, discover.json).
discovery-validate:
bun run discovery:validate
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "purview-dev",
"version": "0.5.0",
"version": "0.5.1",
"private": true,
"description": "Purview-Dev public website and unified documentation portal (workspace root).",
"license": "MIT",
Expand All @@ -23,6 +23,7 @@
"discovery:manifest": "bun run --cwd src discovery:manifest",
"discovery:validate": "bun run --cwd src discovery:validate",
"fetch:releases": "bun run --cwd src fetch:releases",
"fix:projects": "bun run --cwd src fix:projects",
"format": "bun run --cwd src format",
"format:check": "bun run --cwd src format:check",
"lint": "bun run --cwd src lint",
Expand Down
2 changes: 1 addition & 1 deletion src/astro.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ export default defineConfig({
},
{
label: 'NuGet packages',
url: `${SITE.nugetUrl}/search?q=purview`,
url: `${SITE.nugetUrl}/packages?q=purview+kieronlanning`,
description: 'Published packages on nuget.org.',
},
{
Expand Down
Loading
Loading