diff --git a/.gitignore b/.gitignore index 82f2a34..ea5b3b6 100644 --- a/.gitignore +++ b/.gitignore @@ -664,5 +664,5 @@ sketch # Purview addition, not in the SDK's template: the skills CLI's universal install location. An # install is reproducible from skills-lock.json, and it must not appear as an untracked change in -# somebody's working tree. See docs/wiki/Agent-Enablement.md. +# somebody's working tree. See docs/wiki/agents/Agent-Enablement.md. .agents/ diff --git a/AGENTS.md b/AGENTS.md index a21360d..1e6d15f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -56,7 +56,8 @@ demonstrate it. ## Documentation conventions -- **One page per concern**, in `docs/wiki/.md`. Title case, hyphens between words. +- **One page per concern**, in `docs/wiki/
/.md`. The section is the topic folder, + the file name is title case with hyphens between words, and the folder name is lower-case. - **Four sections, in order:** the rule, why, how it is enforced, at your scale. A rule a build cannot check is labelled a review obligation — never described as enforced. `Home.md` and `index.md` are navigation, and `Engineering-Principles.md` is an index that links to the page stating each rule in full. @@ -76,7 +77,7 @@ Authored skills live in `skills//SKILL.md` at the repository root. `.agent CLI's install location for skills from **other** repositories and is gitignored; this repository's own skills are never installed into it, because two copies drift apart. A skill states when it applies in its `description`, keeps the workflow in `SKILL.md`, and pushes detail into `references/`. See -[Agent Skills Distribution](docs/wiki/Agent-Skills-Distribution.md). +[Agent Skills Distribution](docs/wiki/agents/Agent-Skills-Distribution.md). Nothing packs a skill into a NuGet package - `Purview.BuildSdk` 1.0.6 removed skill packaging and the build-time `.agents/` mirror outright. The skills CLI clones the git repository, and that is the only route. @@ -130,13 +131,13 @@ These apply only when the repository persists data; a stateless CLI or a pure li - **A value known before storage is derived, not generated.** Use UUIDv5 over an installation-scoped namespace and key it `ValueGeneratedNever()`, so a sequential convention never overwrites it. See - [Well-Known Identifiers](docs/wiki/Well-Known-Identifiers.md). + [Well-Known Identifiers](docs/wiki/data/Well-Known-Identifiers.md). - **Every other GUID key uses one strategy per store.** SQL Server and PostgreSQL order GUIDs differently, so the strategy is carried as context-options data and applied by a model-finalising - convention. See [GUID Key Strategy](docs/wiki/Guid-Key-Strategy.md). + convention. See [GUID Key Strategy](docs/wiki/data/Guid-Key-Strategy.md). - **EF Core is the boundary.** Use `DbContext` directly rather than a repository added for testability; map value objects once; keep design-time and runtime options in step; apply migrations deliberately. - See [EF Core Integration](docs/wiki/EF-Core-Integration.md). + See [EF Core Integration](docs/wiki/data/EF-Core-Integration.md). - **The runnable evidence is the sample.** `samples/Acme.Persistence` is outside `src/` and outside the canonical solution; `just samples` builds, runs and self-checks it. Run it when you change the sample or an identifier convention. @@ -167,7 +168,7 @@ Before handing work back: `continue-on-error` or `|| true` on a check, no force-push over a protected ref. If a hook is wrong or too slow, change the hook in its own reviewed change. "CI will run the same thing anyway" is a claim about a different run, made by the party being checked — and a bypass leaves no trace, which is why it - is never a judgement call. See [Verification Model](docs/wiki/Verification-Model.md). + is never a judgement call. See [Verification Model](docs/wiki/foundations/Verification-Model.md). - Confirm the requested behaviour and scope are satisfied, and that only intended files changed. - If a rule was added or changed: the page states the failure it prevents, says whether it is enforced or a review obligation, has an "at your scale" section, is in `_Sidebar.md` and the `Home.md` table, and is diff --git a/README.md b/README.md index 01ae9e1..8c3d1fb 100644 --- a/README.md +++ b/README.md @@ -14,31 +14,31 @@ coding agents are enabled to work in a codebase without hand-holding. | -- | -- | | [Getting started](docs/wiki/Getting-Started.md) | What is the smallest repository that satisfies every rule, in the order you build it? | | [Engineering principles](docs/wiki/Engineering-Principles.md) | What are the non-negotiable rules, and where is each one stated in full? | -| [Repository shape](docs/wiki/Repository-Shape.md) | Where does a file go, and what is it called? | -| [Project responsibilities](docs/wiki/Project-Responsibilities.md) | What is each project for, how is it named, and what may it depend on? | -| [Architecture as tests](docs/wiki/Architecture-As-Tests.md) | How does the build refuse a dependency that points the wrong way? | -| [Verification model](docs/wiki/Verification-Model.md) | Which checks run, in which tier, for which change? | -| [Contracts and data exchange](docs/wiki/Contracts-And-Data-Exchange.md) | How do value objects, schemas and results cross a boundary? | -| [Well-known identifiers](docs/wiki/Well-Known-Identifiers.md) | How is an identity derived so every process and restart agrees? | -| [GUID key strategy](docs/wiki/Guid-Key-Strategy.md) | How is a sequential GUID key chosen and applied per store? | -| [EF Core integration](docs/wiki/EF-Core-Integration.md) | How do the context, providers, value objects, models and migrations fit together? | -| [Testing and test data](docs/wiki/Testing-And-Test-Data.md) | How are tests written, and where does their data come from? | -| [Agent enablement](docs/wiki/Agent-Enablement.md) | How is a repository made legible to a coding agent? | -| [Agent skills distribution](docs/wiki/Agent-Skills-Distribution.md) | How is a skill published once and reach an agent? | -| [Agent guidance skills](docs/wiki/Agent-Guidance-Skills.md) | Which shared guidance ships as a skill, and what context comes first? | -| [Documentation convention](docs/wiki/Documentation-Convention.md) | How is the wiki written, structured and published? | -| [Worked examples](docs/wiki/Worked-Examples.md) | What does the reference implementation under `src/` actually demonstrate? | -| [Adopting this at your scale](docs/wiki/Adopting-This-At-Your-Scale.md) | Which parts apply to a small, medium or large repository? | -| [Contributing](docs/wiki/Contributing.md) | How do I change the playbook itself? | -| [Release flow](docs/wiki/Release-Flow.md) | How does a change become a version, and what does a release mean here? | +| [Repository shape](docs/wiki/foundations/Repository-Shape.md) | Where does a file go, and what is it called? | +| [Project responsibilities](docs/wiki/foundations/Project-Responsibilities.md) | What is each project for, how is it named, and what may it depend on? | +| [Architecture as tests](docs/wiki/foundations/Architecture-As-Tests.md) | How does the build refuse a dependency that points the wrong way? | +| [Verification model](docs/wiki/foundations/Verification-Model.md) | Which checks run, in which tier, for which change? | +| [Contracts and data exchange](docs/wiki/data/Contracts-And-Data-Exchange.md) | How do value objects, schemas and results cross a boundary? | +| [Well-known identifiers](docs/wiki/data/Well-Known-Identifiers.md) | How is an identity derived so every process and restart agrees? | +| [GUID key strategy](docs/wiki/data/Guid-Key-Strategy.md) | How is a sequential GUID key chosen and applied per store? | +| [EF Core integration](docs/wiki/data/EF-Core-Integration.md) | How do the context, providers, value objects, models and migrations fit together? | +| [Testing and test data](docs/wiki/testing/Testing-And-Test-Data.md) | How are tests written, and where does their data come from? | +| [Agent enablement](docs/wiki/agents/Agent-Enablement.md) | How is a repository made legible to a coding agent? | +| [Agent skills distribution](docs/wiki/agents/Agent-Skills-Distribution.md) | How is a skill published once and reach an agent? | +| [Agent guidance skills](docs/wiki/agents/Agent-Guidance-Skills.md) | Which shared guidance ships as a skill, and what context comes first? | +| [Documentation convention](docs/wiki/foundations/Documentation-Convention.md) | How is the wiki written, structured and published? | +| [Worked examples](docs/wiki/examples/Worked-Examples.md) | What does the reference implementation under `src/` actually demonstrate? | +| [Adopting this at your scale](docs/wiki/governance/Adopting-This-At-Your-Scale.md) | Which parts apply to a small, medium or large repository? | +| [Contributing](docs/wiki/governance/Contributing.md) | How do I change the playbook itself? | +| [Release flow](docs/wiki/governance/Release-Flow.md) | How does a change become a version, and what does a release mean here? | ## Start here - **New to the playbook?** [Getting started](docs/wiki/Getting-Started.md) walks the smallest repository that satisfies every rule. -- **Adopting it?** [Adopting this at your scale](docs/wiki/Adopting-This-At-Your-Scale.md) picks the +- **Adopting it?** [Adopting this at your scale](docs/wiki/governance/Adopting-This-At-Your-Scale.md) picks the subset that fits, and [`templates/`](templates) is the copy-paste starting point. -- **Want to see it run?** [Worked examples](docs/wiki/Worked-Examples.md) walks the reference +- **Want to see it run?** [Worked examples](docs/wiki/examples/Worked-Examples.md) walks the reference implementation under [`src/`](src), which this repository's own pipeline builds and tests. ## Repository layout diff --git a/docs/wiki/Engineering-Principles.md b/docs/wiki/Engineering-Principles.md index 8678224..26debc5 100644 --- a/docs/wiki/Engineering-Principles.md +++ b/docs/wiki/Engineering-Principles.md @@ -13,16 +13,16 @@ A rule that claims enforcement it does not have is worse than no rule, because p | # | Principle | In one line | Detail | | -- | -- | -- | -- | -| 1 | Convention over configuration | A repository declares as little as possible; one MSBuild SDK supplies the defaults, so a project file is short. | [Repository Shape](Repository-Shape.md) | -| 2 | Identity is derived, never repeated | A name appears once, in the folder and file name; `RootNamespace` and `AssemblyName` are computed from it. | [Repository Shape](Repository-Shape.md) | -| 3 | Architecture is a test, not a diagram | The dependencies a layer may have are asserted by tests, so a wrong `ProjectReference` fails the build. | [Architecture as Tests](Architecture-As-Tests.md), [Project Responsibilities](Project-Responsibilities.md) | -| 4 | The build is the only authority | A convention a build can check is checked by the build; the rest is labelled a review obligation, never described as enforced. | [Documentation Convention](Documentation-Convention.md) | -| 5 | Warnings are not acceptable output | A clean build has no warnings: fix one, suppress it where it occurs with a justification, or turn the rule off deliberately. | [Testing and Test Data](Testing-And-Test-Data.md) | -| 6 | Every claim about a consumer is proved by a consumer | A package that documents how it must be used ships something that builds that documented consumer and asserts the documented outcome. | [Contracts and Data Exchange](Contracts-And-Data-Exchange.md) | -| 7 | Documentation is a build artefact of the repository | The wiki lives in the repository it describes, and the repository owns its `mkdocs.yml`, navigation and `edit_uri`. | [Documentation Convention](Documentation-Convention.md) | -| 8 | Everything a test needs is built by one builder | Domain content in a test comes from `TestBuilder`; a test overrides only the value it is proving. | [Testing and Test Data](Testing-And-Test-Data.md) | -| 9 | An agent is a reader with no memory | A repository states its purpose, layout and conventions in `AGENTS.md`; nothing important is discoverable only from the code. | [Agent Enablement](Agent-Enablement.md) | -| 10 | A change is verified in proportion to its risk | Checks are tiered; a pull request runs the fast tier, and the slow tier is run deliberately. | [Verification Model](Verification-Model.md) | +| 1 | Convention over configuration | A repository declares as little as possible; one MSBuild SDK supplies the defaults, so a project file is short. | [Repository Shape](foundations/Repository-Shape.md) | +| 2 | Identity is derived, never repeated | A name appears once, in the folder and file name; `RootNamespace` and `AssemblyName` are computed from it. | [Repository Shape](foundations/Repository-Shape.md) | +| 3 | Architecture is a test, not a diagram | The dependencies a layer may have are asserted by tests, so a wrong `ProjectReference` fails the build. | [Architecture as Tests](foundations/Architecture-As-Tests.md), [Project Responsibilities](foundations/Project-Responsibilities.md) | +| 4 | The build is the only authority | A convention a build can check is checked by the build; the rest is labelled a review obligation, never described as enforced. | [Documentation Convention](foundations/Documentation-Convention.md) | +| 5 | Warnings are not acceptable output | A clean build has no warnings: fix one, suppress it where it occurs with a justification, or turn the rule off deliberately. | [Testing and Test Data](testing/Testing-And-Test-Data.md) | +| 6 | Every claim about a consumer is proved by a consumer | A package that documents how it must be used ships something that builds that documented consumer and asserts the documented outcome. | [Contracts and Data Exchange](data/Contracts-And-Data-Exchange.md) | +| 7 | Documentation is a build artefact of the repository | The wiki lives in the repository it describes, and the repository owns its `mkdocs.yml`, navigation and `edit_uri`. | [Documentation Convention](foundations/Documentation-Convention.md) | +| 8 | Everything a test needs is built by one builder | Domain content in a test comes from `TestBuilder`; a test overrides only the value it is proving. | [Testing and Test Data](testing/Testing-And-Test-Data.md) | +| 9 | An agent is a reader with no memory | A repository states its purpose, layout and conventions in `AGENTS.md`; nothing important is discoverable only from the code. | [Agent Enablement](agents/Agent-Enablement.md) | +| 10 | A change is verified in proportion to its risk | Checks are tiered; a pull request runs the fast tier, and the slow tier is run deliberately. | [Verification Model](foundations/Verification-Model.md) | ### Conditional persistence rules @@ -32,9 +32,9 @@ silent there. Each is stated in full on its own page. | Rule | In one line | Detail | Page | | -- | -- | -- | -- | -| P1 | A value known before storage is derived, not generated | UUIDv5 over an installation-scoped namespace, keyed `ValueGeneratedNever()` so no generator overwrites it. | [Well-Known Identifiers](Well-Known-Identifiers.md) | -| P2 | A GUID key strategy is chosen once per store | One provider-specific strategy, carried as context-options data and applied to every key by convention. | [GUID Key Strategy](Guid-Key-Strategy.md) | -| P3 | EF Core is the persistence boundary | `DbContext` used directly, value objects mapped once, design-time and runtime options in step, migrations applied deliberately. | [EF Core Integration](EF-Core-Integration.md) | +| P1 | A value known before storage is derived, not generated | UUIDv5 over an installation-scoped namespace, keyed `ValueGeneratedNever()` so no generator overwrites it. | [Well-Known Identifiers](data/Well-Known-Identifiers.md) | +| P2 | A GUID key strategy is chosen once per store | One provider-specific strategy, carried as context-options data and applied to every key by convention. | [GUID Key Strategy](data/Guid-Key-Strategy.md) | +| P3 | EF Core is the persistence boundary | `DbContext` used directly, value objects mapped once, design-time and runtime options in step, migrations applied deliberately. | [EF Core Integration](data/EF-Core-Integration.md) | Enforcement is stated per rule on the linked page. Three of the ten are enforced by the build in a way worth knowing at a glance: identity (rule 2) by `PurviewProjectFileNameMismatch` and the SDK's @@ -45,7 +45,7 @@ says which. ## At your scale Every rule has a smaller version, and taking one before the problem it prevents exists is pure cost. -[Adopting This at Your Scale](Adopting-This-At-Your-Scale.md) decides which rules apply to a small, +[Adopting This at Your Scale](governance/Adopting-This-At-Your-Scale.md) decides which rules apply to a small, medium or large repository, and in what order to adopt them. The conditional persistence rules are the clearest example: a repository that stores nothing takes none @@ -54,11 +54,11 @@ of them, and a repository with low write volume takes only P3. The smaller versi ## See also -- [Repository Shape](Repository-Shape.md) -- [Architecture as Tests](Architecture-As-Tests.md) -- [Verification Model](Verification-Model.md) -- [Testing and Test Data](Testing-And-Test-Data.md) -- [Well-Known Identifiers](Well-Known-Identifiers.md) -- [GUID Key Strategy](Guid-Key-Strategy.md) -- [EF Core Integration](EF-Core-Integration.md) -- [Adopting This at Your Scale](Adopting-This-At-Your-Scale.md) +- [Repository Shape](foundations/Repository-Shape.md) +- [Architecture as Tests](foundations/Architecture-As-Tests.md) +- [Verification Model](foundations/Verification-Model.md) +- [Testing and Test Data](testing/Testing-And-Test-Data.md) +- [Well-Known Identifiers](data/Well-Known-Identifiers.md) +- [GUID Key Strategy](data/Guid-Key-Strategy.md) +- [EF Core Integration](data/EF-Core-Integration.md) +- [Adopting This at Your Scale](governance/Adopting-This-At-Your-Scale.md) diff --git a/docs/wiki/Getting-Started.md b/docs/wiki/Getting-Started.md index 22e2fb7..8189262 100644 --- a/docs/wiki/Getting-Started.md +++ b/docs/wiki/Getting-Started.md @@ -100,7 +100,7 @@ says. `Purview.Telemetry.SourceGenerator`, `Microsoft.Extensions.Telemetry.Abstractions` and `Microsoft.SourceLink.GitHub` are injected by the SDK itself — telemetry and SourceLink are on by default. The rest are the test stack: TUnit is the framework, TUnit.Mocks the substitute library, Bogus -the test-data generator. See [Testing and Test Data](Testing-And-Test-Data.md). +the test-data generator. See [Testing and Test Data](testing/Testing-And-Test-Data.md). ### Versions are properties, packages are items @@ -152,7 +152,7 @@ the reviewer, and it is cheap to keep because the file is read far more often th `NamespacePrefix` must be set **before** the import, because the SDK derives `RootNamespace` from it during `.props` evaluation. From this point every project beneath `src/` gets the target framework, language version, nullable context, analyzers, code-style enforcement and assembly identity without -declaring any of them. See [Repository Shape](Repository-Shape.md). +declaring any of them. See [Repository Shape](foundations/Repository-Shape.md). > **Where the file goes.** MSBuild walks up from each project to the nearest `Directory.Build.props`, so > the import can sit at the repository root or at `src/`. This repository and the multi-project Purview @@ -220,7 +220,7 @@ public sealed record CustomerId ``` `Create` validates, `Hydrate` trusts. That split is the subject of [Contracts and Data -Exchange](Contracts-And-Data-Exchange.md). +Exchange](data/Contracts-And-Data-Exchange.md). > **One trap, immediately.** The SDK strips a list of layer suffixes (`Core`, `Infrastructure`, > `Persistence`, `Abstractions`, …) from `RootNamespace`, so a project called `Infrastructure` declares @@ -279,7 +279,7 @@ public sealed class CustomerIdTests The name is one of a recognised set, so the SDK treats it as a shared testing project: it gets the test packages but not the runner, stays a library, and is referenced automatically by the test projects -beside it. This is where `TestBuilder` lives — see [Testing and Test Data](Testing-And-Test-Data.md). +beside it. This is where `TestBuilder` lives — see [Testing and Test Data](testing/Testing-And-Test-Data.md). ### Step 8 — Point the shared pipeline at the solution @@ -307,14 +307,14 @@ Paths are anchored to the **repository root**, not to the configuration file, so `RunPack` and `ValidatePack` are off because this repository ships no package. The shared workflow defaults both to `true`, so leaving them unset would give a green local build and a failing pipeline. -See [Verification Model](Verification-Model.md). +See [Verification Model](foundations/Verification-Model.md). `TestPatterns` is left at its default, `*Tests.csproj`, on purpose. Discovery and tiering are two mechanisms, and only one of them should carry the tier: `TestPatterns` chooses which project files are discovered, `TestFilter` chooses which discovered tests run. Leave discovery wide and the day you add `Domain.IntegrationTests` it is kept out of the pull-request tier by its category alone, with no second edit. Narrow `TestPatterns` and you have to remember both. See [Verification -Model](Verification-Model.md). +Model](foundations/Verification-Model.md). ### Step 9 — Add the caller workflow @@ -345,8 +345,8 @@ jobs: The two pack switches repeat `Build:RunPack` and `Build:ValidatePack` from the configuration, so the workflow and the JSON agree about what a green build means. The workflow is a caller; the pipeline -itself lives in one shared repository. See [Verification Model](Verification-Model.md) and -[Release Flow](Release-Flow.md). +itself lives in one shared repository. See [Verification Model](foundations/Verification-Model.md) and +[Release Flow](governance/Release-Flow.md). ### Step 10 — Add the wiki @@ -367,14 +367,14 @@ markdown_extensions: [admonition, attr_list, md_in_html, pymdownx.details, pymdo Then `docs/wiki/index.md`, `docs/wiki/Home.md` and `docs/wiki/_Sidebar.md`, and the pages behind them. `_Sidebar.md` is the navigation list, so a new page that is not in it is a page nobody finds. See -[Documentation Convention](Documentation-Convention.md). +[Documentation Convention](foundations/Documentation-Convention.md). ### Step 11 — Make the repository legible to an agent Add `AGENTS.md` at the root: purpose, layout table, conventions, completion checklist, local commands. Then install the SDK's own skills with `npx skills add purview-dev/build-sdk`, so an agent gets that guidance without you writing it. Installation is explicit - no build writes into an agent directory. -See [Agent Enablement](Agent-Enablement.md). +See [Agent Enablement](agents/Agent-Enablement.md). ### Step 12 — Add the local tools and the commands that run them @@ -476,9 +476,9 @@ three conditional rules on their own pages rather than inventing a shape: | Concern | Rule | Page | | -- | -- | -- | -| The context and the model | `DbContext` is the boundary; map value objects once; design time matches runtime; migrate deliberately | [EF Core Integration](EF-Core-Integration.md) | -| A value known before storage | Derive it with UUIDv5 over an installation-scoped namespace and key it `ValueGeneratedNever()` | [Well-Known Identifiers](Well-Known-Identifiers.md) | -| Every other GUID key | One strategy per store, applied by a model-finalising convention | [GUID Key Strategy](Guid-Key-Strategy.md) | +| The context and the model | `DbContext` is the boundary; map value objects once; design time matches runtime; migrate deliberately | [EF Core Integration](data/EF-Core-Integration.md) | +| A value known before storage | Derive it with UUIDv5 over an installation-scoped namespace and key it `ValueGeneratedNever()` | [Well-Known Identifiers](data/Well-Known-Identifiers.md) | +| Every other GUID key | One strategy per store, applied by a model-finalising convention | [GUID Key Strategy](data/Guid-Key-Strategy.md) | The working example is `samples/Acme.Persistence`, run with `just samples`. It sits outside `src/` so the reference implementation in this repository stays in-memory and the canonical solution keeps its shape. @@ -503,13 +503,13 @@ repository: which concern lives where, and what refuses a change that breaks it. ## At your scale -This page is the floor, not the whole playbook. [Adopting This at Your Scale](Adopting-This-At-Your-Scale.md) +This page is the floor, not the whole playbook. [Adopting This at Your Scale](governance/Adopting-This-At-Your-Scale.md) decides which parts to take for a small, medium or large repository, and [Worked -Examples](Worked-Examples.md) walks the reference implementation that results from taking all of them. +Examples](examples/Worked-Examples.md) walks the reference implementation that results from taking all of them. ## See also - [Engineering Principles](Engineering-Principles.md) -- [Repository Shape](Repository-Shape.md) -- [Adopting This at Your Scale](Adopting-This-At-Your-Scale.md) -- [Worked Examples](Worked-Examples.md) +- [Repository Shape](foundations/Repository-Shape.md) +- [Adopting This at Your Scale](governance/Adopting-This-At-Your-Scale.md) +- [Worked Examples](examples/Worked-Examples.md) diff --git a/docs/wiki/Home.md b/docs/wiki/Home.md index 8742f17..8c9f5d4 100644 --- a/docs/wiki/Home.md +++ b/docs/wiki/Home.md @@ -9,6 +9,29 @@ The conventions were previously discoverable only by reading the repositories an from the repetition. They are stated here once, with the evidence and the trade-offs attached, and scaled so that a repository adopting them can take the part that fits. +## How this wiki is organised + +The wiki is one folder per topic, and the sidebar and the tables below carry the same sections in the +same order. `_Sidebar.md` is what the published site reads for page order, so a page that is not listed +there has no place in the navigation. A page's folder is part of its published URL +(`foundations/Repository-Shape.md` is published under `foundations/`), so a page moves folder only when +it changes topic. + +| Section | Where it lives | +| -- | -- | +| Get started | the wiki root | +| Repository foundations | `foundations/` | +| Data and persistence | `data/` | +| Testing | `testing/` | +| Working with agents | `agents/` | +| Adoption and governance | `governance/` | +| The reference implementation | `examples/` | + +Five pages stay at the wiki root: `Home.md` is this hub, `index.md` is the landing page, `_Sidebar.md` +is the navigation, `Getting-Started.md` is the first page to read, and `Engineering-Principles.md` is +the index that links each rule to the page stating it in full. Every other content page belongs to a +topic folder. + ## How to read a page Every content page follows the same shape: @@ -28,43 +51,85 @@ This page and [`index.md`](index.md) are navigation rather than rules, and [Engineering Principles](Engineering-Principles.md) is an index that links to the page stating each rule in full. -## The playbook +## Get started + +Read these first. They establish the vocabulary and the smallest repository that satisfies every rule. -| Page | Covers | +| Page | Answers | | -- | -- | | [Getting Started](Getting-Started.md) | The smallest repository that satisfies every rule, in the order you would build it. | | [Engineering Principles](Engineering-Principles.md) | The non-negotiable rules, and where the authoritative statement of each one lives. | -| [Repository Shape](Repository-Shape.md) | Where a file goes, what it is called, and how a project's name becomes its namespace. | -| [Project Responsibilities](Project-Responsibilities.md) | What each project is for, how it is named, and what it may depend on. | -| [Architecture as Tests](Architecture-As-Tests.md) | How the build refuses a dependency that points the wrong way. | -| [Verification Model](Verification-Model.md) | Which checks run, in which tier, for which change. | -| [Contracts and Data Exchange](Contracts-And-Data-Exchange.md) | How value objects, schemas and results cross a boundary. | -| [Well-Known Identifiers](Well-Known-Identifiers.md) | Identities whose value must be identical in every process and restart, derived with UUIDv5. | -| [GUID Key Strategy](Guid-Key-Strategy.md) | Choosing and applying a store-ordered GUID key for SQL Server or PostgreSQL. | -| [EF Core Integration](EF-Core-Integration.md) | How the context, providers, value objects, models and migrations fit together. | -| [Testing and Test Data](Testing-And-Test-Data.md) | How tests are written, and where their data comes from. | -| [Agent Enablement](Agent-Enablement.md) | How a repository is made legible to a coding agent. | -| [Agent Skills Distribution](Agent-Skills-Distribution.md) | How a skill is published once and reaches both a package's consumers and an agent's own directories. | -| [Agent Guidance Skills](Agent-Guidance-Skills.md) | The shared architecture, telemetry and persistence guidance, and the context an agent must establish first. | -| [Documentation Convention](Documentation-Convention.md) | How the wiki is written, structured and published. | -| [Cross-Repository Harvest](Cross-Repository-Harvest.md) | Which repository owns which convention, how it is read at `main`, and what the snapshot records. | -| [Worked Examples](Worked-Examples.md) | The reference implementation in this repository, walked end to end. | -| [Adopting This at Your Scale](Adopting-This-At-Your-Scale.md) | Which parts apply to a small, medium or large repository. | -| [Contributing](Contributing.md) | How to change the playbook itself. | -| [Release Flow](Release-Flow.md) | How a change becomes a version, and what a release means here. | + +## Repository foundations + +How a repository is laid out, what each project owns, how the architecture is enforced, and how the +documentation itself is written. + +| Page | Answers | +| -- | -- | +| [Repository Shape](foundations/Repository-Shape.md) | Where a file goes, what it is called, and how a project's name becomes its namespace. | +| [Project Responsibilities](foundations/Project-Responsibilities.md) | What each project is for, how it is named, and what it may depend on. | +| [Architecture as Tests](foundations/Architecture-As-Tests.md) | How the build refuses a dependency that points the wrong way. | +| [Verification Model](foundations/Verification-Model.md) | Which checks run, in which tier, for which change. | +| [Documentation Convention](foundations/Documentation-Convention.md) | How the wiki is written, structured and published. | + +## Data and persistence + +These apply only when the repository persists data. Value objects, schemas and results cross a +boundary first; the identifier and EF Core rules then decide how that data is stored. + +| Page | Answers | +| -- | -- | +| [Contracts and Data Exchange](data/Contracts-And-Data-Exchange.md) | How value objects, schemas and results cross a boundary. | +| [Well-Known Identifiers](data/Well-Known-Identifiers.md) | Identities whose value must be identical in every process and restart, derived with UUIDv5. | +| [GUID Key Strategy](data/Guid-Key-Strategy.md) | Choosing and applying a store-ordered GUID key for SQL Server or PostgreSQL. | +| [EF Core Integration](data/EF-Core-Integration.md) | How the context, providers, value objects, models and migrations fit together. | + +## Testing + +How tests are written, and where their data comes from. + +| Page | Answers | +| -- | -- | +| [Testing and Test Data](testing/Testing-And-Test-Data.md) | How tests are written, and where their data comes from. | + +## Working with agents + +How a repository is made legible to a coding agent, and how shared guidance is published as a skill. + +| Page | Answers | +| -- | -- | +| [Agent Enablement](agents/Agent-Enablement.md) | How a repository is made legible to a coding agent. | +| [Agent Skills Distribution](agents/Agent-Skills-Distribution.md) | How a skill is published once and reaches both a package's consumers and an agent's own directories. | +| [Agent Guidance Skills](agents/Agent-Guidance-Skills.md) | The shared architecture, telemetry and persistence guidance, and the context an agent must establish first. | + +## Adoption and governance + +Which parts of the playbook apply at your size, how a claim about another repository is checked, and +how a change to either the playbook or a release is made. + +| Page | Answers | +| -- | -- | +| [Adopting This at Your Scale](governance/Adopting-This-At-Your-Scale.md) | Which parts apply to a small, medium or large repository. | +| [Cross-Repository Harvest](governance/Cross-Repository-Harvest.md) | Which repository owns which convention, how it is read at `main`, and what the snapshot records. | +| [Contributing](governance/Contributing.md) | How to change the playbook itself. | +| [Release Flow](governance/Release-Flow.md) | How a change becomes a version, and what a release means here. | ## The reference implementation `src/` in this repository is a deliberately small layered repository that is built, linted and tested by the same pipeline every Purview repository uses. It exists so the rules in this playbook are not just prose: the dependency-direction rules fail the build when they are broken, and the test-data -conventions are shown in the form they are meant to be copied. [Worked -Examples](Worked-Examples.md) walks it end to end. +conventions are shown in the form they are meant to be copied. + +| Page | Answers | +| -- | -- | +| [Worked Examples](examples/Worked-Examples.md) | The reference implementation in this repository, walked end to end. | The conventions that need EF Core live in `samples/Acme.Persistence`, a standalone runnable sample started with `just samples`. It is outside `src/` so the reference implementation stays in-memory. -[EF Core Integration](EF-Core-Integration.md), [Well-Known Identifiers](Well-Known-Identifiers.md) and -[GUID Key Strategy](Guid-Key-Strategy.md) are the rules it proves. +[EF Core Integration](data/EF-Core-Integration.md), [Well-Known Identifiers](data/Well-Known-Identifiers.md) +and [GUID Key Strategy](data/Guid-Key-Strategy.md) are the rules it proves. ## Provenance @@ -77,4 +142,4 @@ and [event-sourcing](https://github.com/purview-dev/event-sourcing) (data exchan [purview-dev.github.io](https://github.com/purview-dev/purview-dev.github.io) (the public catalogue, and documentation as a published surface). Each page names the public repository, specification or package a claim can be checked against, so a claim can always be checked against running code; -[Cross-Repository Harvest](Cross-Repository-Harvest.md) is how that claim stays true. +[Cross-Repository Harvest](governance/Cross-Repository-Harvest.md) is how that claim stays true. diff --git a/docs/wiki/_Sidebar.md b/docs/wiki/_Sidebar.md index bb0b0d8..ae65486 100644 --- a/docs/wiki/_Sidebar.md +++ b/docs/wiki/_Sidebar.md @@ -1,21 +1,33 @@ + + - [Home](Home.md) -- [Getting Started](Getting-Started.md) -- [Engineering Principles](Engineering-Principles.md) -- [Repository Shape](Repository-Shape.md) -- [Project Responsibilities](Project-Responsibilities.md) -- [Architecture as Tests](Architecture-As-Tests.md) -- [Verification Model](Verification-Model.md) -- [Contracts and Data Exchange](Contracts-And-Data-Exchange.md) -- [Well-Known Identifiers](Well-Known-Identifiers.md) -- [GUID Key Strategy](Guid-Key-Strategy.md) -- [EF Core Integration](EF-Core-Integration.md) -- [Testing and Test Data](Testing-And-Test-Data.md) -- [Agent Enablement](Agent-Enablement.md) -- [Agent Skills Distribution](Agent-Skills-Distribution.md) -- [Agent Guidance Skills](Agent-Guidance-Skills.md) -- [Documentation Convention](Documentation-Convention.md) -- [Cross-Repository Harvest](Cross-Repository-Harvest.md) -- [Worked Examples](Worked-Examples.md) -- [Adopting This at Your Scale](Adopting-This-At-Your-Scale.md) -- [Contributing](Contributing.md) -- [Release Flow](Release-Flow.md) +- **Get started** + - [Getting Started](Getting-Started.md) + - [Engineering Principles](Engineering-Principles.md) +- **Repository foundations** + - [Repository Shape](foundations/Repository-Shape.md) + - [Project Responsibilities](foundations/Project-Responsibilities.md) + - [Architecture as Tests](foundations/Architecture-As-Tests.md) + - [Verification Model](foundations/Verification-Model.md) + - [Documentation Convention](foundations/Documentation-Convention.md) +- **Data and persistence** + - [Contracts and Data Exchange](data/Contracts-And-Data-Exchange.md) + - [Well-Known Identifiers](data/Well-Known-Identifiers.md) + - [GUID Key Strategy](data/Guid-Key-Strategy.md) + - [EF Core Integration](data/EF-Core-Integration.md) +- **Testing** + - [Testing and Test Data](testing/Testing-And-Test-Data.md) +- **Working with agents** + - [Agent Enablement](agents/Agent-Enablement.md) + - [Agent Skills Distribution](agents/Agent-Skills-Distribution.md) + - [Agent Guidance Skills](agents/Agent-Guidance-Skills.md) +- **Adoption and governance** + - [Adopting This at Your Scale](governance/Adopting-This-At-Your-Scale.md) + - [Cross-Repository Harvest](governance/Cross-Repository-Harvest.md) + - [Contributing](governance/Contributing.md) + - [Release Flow](governance/Release-Flow.md) +- **The reference implementation** + - [Worked Examples](examples/Worked-Examples.md) diff --git a/docs/wiki/Agent-Enablement.md b/docs/wiki/agents/Agent-Enablement.md similarity index 98% rename from docs/wiki/Agent-Enablement.md rename to docs/wiki/agents/Agent-Enablement.md index 1ddeaaf..875109b 100644 --- a/docs/wiki/Agent-Enablement.md +++ b/docs/wiki/agents/Agent-Enablement.md @@ -152,6 +152,6 @@ never appears in a status output. ## See also - [Agent Skills Distribution](Agent-Skills-Distribution.md) -- [Documentation Convention](Documentation-Convention.md) -- [Repository Shape](Repository-Shape.md) +- [Documentation Convention](../foundations/Documentation-Convention.md) +- [Repository Shape](../foundations/Repository-Shape.md) - [Agent Skills specification](https://agentskills.io/specification) diff --git a/docs/wiki/Agent-Guidance-Skills.md b/docs/wiki/agents/Agent-Guidance-Skills.md similarity index 96% rename from docs/wiki/Agent-Guidance-Skills.md rename to docs/wiki/agents/Agent-Guidance-Skills.md index d8023a7..7d3b70e 100644 --- a/docs/wiki/Agent-Guidance-Skills.md +++ b/docs/wiki/agents/Agent-Guidance-Skills.md @@ -108,7 +108,7 @@ initialisation order. This guidance activates only when persistence is real. For a stateless CLI or a pure library, the correct output is silence. The EF Core integration rules are in [EF Core -Integration](EF-Core-Integration.md); the decision diagram below is the identifier-specific branch. +Integration](../data/EF-Core-Integration.md); the decision diagram below is the identifier-specific branch. **Diagram N — persistence-specific GUID strategy selection.** @@ -157,8 +157,8 @@ serves both providers, the strategy is carried as data on the context options, n the value is known before the row exists — a system tenant, a seeded reference row, an installation's service principal — derive it with UUIDv5 in an installation-scoped namespace and configure `ValueGeneratedNever()`. The full rule, catalogue and tests are on [Well-Known -Identifiers](Well-Known-Identifiers.md); the convention that must skip it is on [GUID Key -Strategy](Guid-Key-Strategy.md). +Identifiers](../data/Well-Known-Identifiers.md); the convention that must skip it is on [GUID Key +Strategy](../data/Guid-Key-Strategy.md). No **NuGet** package provides the *strategy/convention pattern*. A reviewed generator such as `FastGuid` supplies a store-ordered implementation, but the witness, options extension, value generator @@ -170,7 +170,7 @@ rollover and thread safety are all live hazards, and the failure shows up as dup The persistence skill also covers the non-identifier half of the same decision, because an agent that is already choosing a store is the agent that will otherwise invent a repository over `DbContext`. The full -rule is on [EF Core Integration](EF-Core-Integration.md); the four points worth keeping in mind are: +rule is on [EF Core Integration](../data/EF-Core-Integration.md); the four points worth keeping in mind are: - **`DbContext` is the boundary.** No `IRepository` or unit-of-work wrapper added for testability; `Purview.Containers` gives a real database in tests. @@ -235,5 +235,5 @@ thing when read. - [Agent Skills Distribution](Agent-Skills-Distribution.md) — how these skills reach a consumer - [Agent Enablement](Agent-Enablement.md) -- [Engineering Principles](Engineering-Principles.md) -- [Adopting This at Your Scale](Adopting-This-At-Your-Scale.md) +- [Engineering Principles](../Engineering-Principles.md) +- [Adopting This at Your Scale](../governance/Adopting-This-At-Your-Scale.md) diff --git a/docs/wiki/Agent-Skills-Distribution.md b/docs/wiki/agents/Agent-Skills-Distribution.md similarity index 99% rename from docs/wiki/Agent-Skills-Distribution.md rename to docs/wiki/agents/Agent-Skills-Distribution.md index d10c39e..9706a2e 100644 --- a/docs/wiki/Agent-Skills-Distribution.md +++ b/docs/wiki/agents/Agent-Skills-Distribution.md @@ -262,6 +262,6 @@ belong in `skills/` at all. A skill here ships to somebody else; put repository- ## See also - [Agent Enablement](Agent-Enablement.md) — `AGENTS.md`, `.agents/`, and what makes a good skill -- [Documentation Convention](Documentation-Convention.md) +- [Documentation Convention](../foundations/Documentation-Convention.md) - [skills CLI](https://github.com/vercel-labs/skills) - [Agent Skills specification](https://agentskills.io/specification) diff --git a/docs/wiki/Contracts-And-Data-Exchange.md b/docs/wiki/data/Contracts-And-Data-Exchange.md similarity index 98% rename from docs/wiki/Contracts-And-Data-Exchange.md rename to docs/wiki/data/Contracts-And-Data-Exchange.md index ba5f183..68dbc1b 100644 --- a/docs/wiki/Contracts-And-Data-Exchange.md +++ b/docs/wiki/data/Contracts-And-Data-Exchange.md @@ -186,10 +186,10 @@ a hope. ## See also -- [Worked Examples](Worked-Examples.md) +- [Worked Examples](../examples/Worked-Examples.md) - [EF Core Integration](EF-Core-Integration.md) — value converters and value-object keys in the model - [Well-Known Identifiers](Well-Known-Identifiers.md) — value objects that carry a derived identity -- [Testing and Test Data](Testing-And-Test-Data.md) +- [Testing and Test Data](../testing/Testing-And-Test-Data.md) - [value-objects](https://github.com/purview-dev/value-objects) - [results](https://github.com/purview-dev/results) - [zodsharp](https://github.com/purview-dev/zodsharp) diff --git a/docs/wiki/EF-Core-Integration.md b/docs/wiki/data/EF-Core-Integration.md similarity index 96% rename from docs/wiki/EF-Core-Integration.md rename to docs/wiki/data/EF-Core-Integration.md index 108026a..fdff1ad 100644 --- a/docs/wiki/EF-Core-Integration.md +++ b/docs/wiki/data/EF-Core-Integration.md @@ -90,8 +90,8 @@ needs the design-time parity and the cache key if the model varies at design tim | One owner per generated value | Review, plus the tests below in the adopting repository | | Design-time and runtime options agree | An integration test that builds the model both ways and compares the snapshot | | The model cache key covers the model's inputs | A test with two strategies and one context type asserts two models | -| Migrations are applied deliberately | Review, and the `Migrator` host in [Project Responsibilities](Project-Responsibilities.md) | -| Integration tests use a real store | The `*.IntegrationTests` project name and the `Purview.Containers` rule in [Testing and Test Data](Testing-And-Test-Data.md) | +| Migrations are applied deliberately | Review, and the `Migrator` host in [Project Responsibilities](../foundations/Project-Responsibilities.md) | +| Integration tests use a real store | The `*.IntegrationTests` project name and the `Purview.Containers` rule in [Testing and Test Data](../testing/Testing-And-Test-Data.md) | | The connection string stays out of source and telemetry | Review; in an adopting repository, a secret scanner and a redaction test turn it into a build failure | The checks worth writing in an adopting repository are small and specific: @@ -129,6 +129,6 @@ says so rather than claiming a check it does not have. - [Well-Known Identifiers](Well-Known-Identifiers.md) — the derived owner of a key - [GUID Key Strategy](Guid-Key-Strategy.md) — the generated owner, and the full convention - [Contracts and Data Exchange](Contracts-And-Data-Exchange.md) — value objects and their converters -- [Testing and Test Data](Testing-And-Test-Data.md) — real stores and container-backed suites -- [Project Responsibilities](Project-Responsibilities.md) — Persistence owns definitions, Migrator executes them +- [Testing and Test Data](../testing/Testing-And-Test-Data.md) — real stores and container-backed suites +- [Project Responsibilities](../foundations/Project-Responsibilities.md) — Persistence owns definitions, Migrator executes them - [Working with EF Core](https://learn.microsoft.com/en-us/ef/core/) — the framework's own documentation diff --git a/docs/wiki/Guid-Key-Strategy.md b/docs/wiki/data/Guid-Key-Strategy.md similarity index 99% rename from docs/wiki/Guid-Key-Strategy.md rename to docs/wiki/data/Guid-Key-Strategy.md index 8d5d228..df1e10a 100644 --- a/docs/wiki/Guid-Key-Strategy.md +++ b/docs/wiki/data/Guid-Key-Strategy.md @@ -39,7 +39,7 @@ The complete implementation is `samples/Acme.Persistence` at the repository root and runs it, and `--provider` selects SQL Server, PostgreSQL or the UUIDv7 fallback. The page shows the parts that carry the decision, and the sample is the copyable whole. It lives outside `src/` because the reference implementation there is in-memory by design, and adding EF Core, a persistence project and a -database would contradict [Worked Examples](Worked-Examples.md). [EF Core +database would contradict [Worked Examples](../examples/Worked-Examples.md). [EF Core Integration](EF-Core-Integration.md) states the model, composition and migration rules the sample also has to satisfy. @@ -581,4 +581,4 @@ executable subset — monotonicity, the UUIDv7 trap, timestamp round-trips and r - [EF Core Integration](EF-Core-Integration.md) — the context, model and migration rules around it - [Contracts and Data Exchange](Contracts-And-Data-Exchange.md) — value-object identifiers and their converters -- [Worked Examples](Worked-Examples.md) — why `src/` has no persistence to compile these against +- [Worked Examples](../examples/Worked-Examples.md) — why `src/` has no persistence to compile these against diff --git a/docs/wiki/Well-Known-Identifiers.md b/docs/wiki/data/Well-Known-Identifiers.md similarity index 99% rename from docs/wiki/Well-Known-Identifiers.md rename to docs/wiki/data/Well-Known-Identifiers.md index be96179..83fcde5 100644 --- a/docs/wiki/Well-Known-Identifiers.md +++ b/docs/wiki/data/Well-Known-Identifiers.md @@ -68,7 +68,7 @@ for a small, known set of identities; every other key takes [GUID Key Strategy]( The complete implementation is `samples/Acme.Persistence` at the repository root; `just samples` builds and runs it. The page shows the parts that carry the decision, and the sample is the copyable whole. It lives outside `src/` because the reference implementation there is in-memory by design, and adding EF -Core, a persistence project and a database would contradict [Worked Examples](Worked-Examples.md). +Core, a persistence project and a database would contradict [Worked Examples](../examples/Worked-Examples.md). ### 1. The helper @@ -313,4 +313,4 @@ is why the helper above exists rather than a package reference. - [GUID Key Strategy](Guid-Key-Strategy.md) — the sequential keys every other table uses - [EF Core Integration](EF-Core-Integration.md) — mapping the key and the bootstrap in the model - [Contracts and Data Exchange](Contracts-And-Data-Exchange.md) — value objects that carry an identifier -- [Worked Examples](Worked-Examples.md) — why `src/` has no persistence +- [Worked Examples](../examples/Worked-Examples.md) — why `src/` has no persistence diff --git a/docs/wiki/Worked-Examples.md b/docs/wiki/examples/Worked-Examples.md similarity index 93% rename from docs/wiki/Worked-Examples.md rename to docs/wiki/examples/Worked-Examples.md index c2eef44..8498fbc 100644 --- a/docs/wiki/Worked-Examples.md +++ b/docs/wiki/examples/Worked-Examples.md @@ -239,7 +239,7 @@ public async Task RegisterAsync_GivenAnAlreadyRegisteredConvention_DoesNotStoreI ``` **`Architecture.UnitTests`** runs two kinds of rule. `DependencyDirectionTests` is the four rules from -[Architecture as Tests](Architecture-As-Tests.md), reading the compiled assemblies; it is the reason the +[Architecture as Tests](../foundations/Architecture-As-Tests.md), reading the compiled assemblies; it is the reason the `Application` project file carries a comment explaining that a reference to `Infrastructure` would fail the build. `ArchitectureTests` derives from `PurviewArchitectureTests` and enforces the policy in `.config/architecture-policy.json`, so the dependency matrix, naming, sibling-independence, composition, @@ -255,7 +255,7 @@ repository, and that a reviewer would otherwise have to remember, belongs in a t ## The test data builder `TestBuilder` is flat rather than grouped, and -[Testing and Test Data](Testing-And-Test-Data.md#two-constraints-that-shaped-the-builder) explains why. The +[Testing and Test Data](../testing/Testing-And-Test-Data.md#two-constraints-that-shaped-the-builder) explains why. The contract is the interesting part: ```csharp @@ -322,13 +322,13 @@ The fastest way to understand a rule is to watch it fail. Three edits, each of w [containers](https://github.com/purview-dev/containers) is the reference for them. - **No persistence in `src/`.** The adapter is in-memory. There is no migration, no schema and no connection string in the canonical solution. -- **No persistence-specific identifier code in `src/`.** [Well-Known Identifiers](Well-Known-Identifiers.md), - [GUID Key Strategy](Guid-Key-Strategy.md) and [EF Core Integration](EF-Core-Integration.md) are +- **No persistence-specific identifier code in `src/`.** [Well-Known Identifiers](../data/Well-Known-Identifiers.md), + [GUID Key Strategy](../data/Guid-Key-Strategy.md) and [EF Core Integration](../data/EF-Core-Integration.md) are implemented by the standalone sample at `samples/Acme.Persistence`. `just samples` builds and runs it; it sits outside the canonical `src/` solution because the reference implementation here is in-memory by design. - **No web layer.** The result-to-response mapping in [Contracts and Data - Exchange](Contracts-And-Data-Exchange.md) is described, not implemented, because + Exchange](../data/Contracts-And-Data-Exchange.md) is described, not implemented, because [results](https://github.com/purview-dev/results) already implements it and a second implementation here would be a worse copy. - **No integration tier.** Every test is deterministic, so the pipeline needs no second job. @@ -338,12 +338,12 @@ The fastest way to understand a rule is to watch it fail. Three edits, each of w This is the **Medium** profile: a few layers, a shared testing project, and architecture tests. A small repository takes the SDK import, `Directory.Packages.props`, `AGENTS.md` and `TestBuilder` and stops there; a large one adds pack validation, consumer verification and a release gate. [Adopting This at Your -Scale](Adopting-This-At-Your-Scale.md) is the page that decides. +Scale](../governance/Adopting-This-At-Your-Scale.md) is the page that decides. ## See also -- [Getting Started](Getting-Started.md) -- [Architecture as Tests](Architecture-As-Tests.md) -- [Testing and Test Data](Testing-And-Test-Data.md) -- [Contracts and Data Exchange](Contracts-And-Data-Exchange.md) -- [EF Core Integration](EF-Core-Integration.md) +- [Getting Started](../Getting-Started.md) +- [Architecture as Tests](../foundations/Architecture-As-Tests.md) +- [Testing and Test Data](../testing/Testing-And-Test-Data.md) +- [Contracts and Data Exchange](../data/Contracts-And-Data-Exchange.md) +- [EF Core Integration](../data/EF-Core-Integration.md) diff --git a/docs/wiki/Architecture-As-Tests.md b/docs/wiki/foundations/Architecture-As-Tests.md similarity index 98% rename from docs/wiki/Architecture-As-Tests.md rename to docs/wiki/foundations/Architecture-As-Tests.md index 10b6930..c2c3111 100644 --- a/docs/wiki/Architecture-As-Tests.md +++ b/docs/wiki/foundations/Architecture-As-Tests.md @@ -141,7 +141,7 @@ rather than *from* them. A shared testing project's internals are not visible to The corollary is that an `internal` helper is not an option, and a `public` nested type is a build error — the SDK ships `dotnet_diagnostic.CA1034.severity = error`, and `PRSGD0008` refuses to let a repository add `CA1034` to `NoWarn`. Factories therefore sit flat on the builder class rather than in nested groups. See -[Testing and Test Data](Testing-And-Test-Data.md). +[Testing and Test Data](../testing/Testing-And-Test-Data.md). ## What these tests do not cover @@ -183,5 +183,5 @@ are adopted with a policy file and one derived test class rather than with C#. S - [Repository Shape](Repository-Shape.md) - [Verification Model](Verification-Model.md) -- [Testing and Test Data](Testing-And-Test-Data.md) -- [Worked Examples](Worked-Examples.md) +- [Testing and Test Data](../testing/Testing-And-Test-Data.md) +- [Worked Examples](../examples/Worked-Examples.md) diff --git a/docs/wiki/Documentation-Convention.md b/docs/wiki/foundations/Documentation-Convention.md similarity index 72% rename from docs/wiki/Documentation-Convention.md rename to docs/wiki/foundations/Documentation-Convention.md index 97f0145..c624ef7 100644 --- a/docs/wiki/Documentation-Convention.md +++ b/docs/wiki/foundations/Documentation-Convention.md @@ -9,19 +9,28 @@ its navigation and its `edit_uri`. | -- | -- | | `docs/wiki/index.md` | The landing page. Short, with links in. | | `docs/wiki/Home.md` | The hub: what the project is, how to read a page, and a table linking every page. | -| `docs/wiki/_Sidebar.md` | The navigation list. The leading underscore keeps it out of the content listing. | -| `docs/wiki/.md` | One page per concern. Title case, hyphens between words. | +| `docs/wiki/_Sidebar.md` | The navigation list, grouped by section. The leading underscore keeps it out of the content listing. | +| `docs/wiki/
/.md` | One page per concern, in the lower-case folder for its topic. Title case file name, hyphens between words. | | `mkdocs.yml` | Site configuration; `docs_dir: docs/wiki`. | | `README.md` | The repository's front door on GitHub. Points into the wiki; does not duplicate it. | | `AGENTS.md` | The agent's front door. Points into the wiki; does not duplicate it. | +**Folders are sections.** A content page lives in the topic folder its section names — this playbook uses +`foundations/`, `data/`, `testing/`, `agents/`, `governance/` and `examples/` — and the sidebar and the +`Home.md` tables carry those sections in the same order. A page's folder is part of its published URL, so +`foundations/Repository-Shape.md` is published under `foundations/`; move a page between folders only when +its topic changes, because every inbound link has to move with it. Only the navigation and entry pages stay +at the wiki root: `Home.md`, `index.md`, `_Sidebar.md`, and the getting-started and principles pages that +the landing page links first. A wiki with one page needs no folders; add a folder when a topic has enough +pages that a flat list stops being readable. + **Scope.** This is the layout of a repository that publishes a site, and `docs/wiki` is the folder this playbook publishes from. Of the sixteen public repositories in the organisation, twelve use `docs/wiki`; `architests`, `value-objects` and `purview-dev.github.io` publish from `docs`, and `pm-skills` publishes no documentation folder at all, documenting itself through its skills. What the rule requires is the part those repositories share: the documentation lives with the code it describes, and the repository owns its `mkdocs.yml`. The folder name is the part that varies. -[Cross-Repository Harvest](Cross-Repository-Harvest.md) records the deviations by name. +[Cross-Repository Harvest](../governance/Cross-Repository-Harvest.md) records the deviations by name. ## Why @@ -32,6 +41,10 @@ with no owner and no review path is wrong within one release, and nobody can tel and `Home.md` is what a reader lands on. A page in neither is a page that exists only for people who already know its URL — which is to say, for nobody. +**A flat folder becomes a search problem.** Twenty pages in one directory is a list nobody scans; the +same twenty under six topic folders is a map. The folder also puts the topic in the URL, so a link tells +the reader where in the playbook they are about to land. + **Three front doors, three audiences.** `README.md` is for someone deciding whether to use the thing. `Home.md` is for someone who has decided and needs to know where to look. `AGENTS.md` is for an agent that needs the layout and the conventions. They link to the same pages and should not restate them; a fact @@ -117,7 +130,7 @@ a real failure. Naming the repository turns a claim into something a reader can and it is the fastest way for a reader to decide whether the rule applies to them. Then check the name is still the current one: a renamed repository keeps resolving through a redirect, so a stale citation looks healthy until it is compared with the organisation. [Cross-Repository -Harvest](Cross-Repository-Harvest.md) is that comparison, and the snapshot it records. +Harvest](../governance/Cross-Repository-Harvest.md) is that comparison, and the snapshot it records. ## Writing style @@ -137,28 +150,34 @@ Harvest](Cross-Repository-Harvest.md) is that comparison, and the snapshot it re | Rule | Enforced by | | -- | -- | | The site configuration is present and points at `docs/wiki` | Review | -| Every content page is in `_Sidebar.md` and the `Home.md` table, and their links resolve | `DocumentationTests` | +| Every content page, including pages in topic folders, is in `_Sidebar.md` and the `Home.md` table | `DocumentationTests` | +| The sidebar sections and the `Home.md` headings carry the same labels, in the same order | `DocumentationTests` | +| Every relative link in every page resolves | `DocumentationTests` | | Pages follow the four-section shape | Review | +| A page sits in the folder for its section | Review | | Fences declare a language | `DocumentationTests` | | `README.md` and `AGENTS.md` point in rather than duplicate | Review | -The navigation and the fences are the two conventions a machine can check, and they are the two that -break silently: a page nobody can reach is a page that does not exist, and a bare fence renders as an -untyped block. Both are enforced by `DocumentationTests` in `src/tests/Repository.UnitTests`. The rest -is a review obligation, and this page says so rather than implying otherwise. +The navigation, the links and the fences are the conventions a machine can check, and they are the ones +that break silently: a page nobody can reach is a page that does not exist, a link into the wrong folder +is a 404 nobody sees in review, and a bare fence renders as an untyped block. `DocumentationTests` in +`src/tests/Repository.UnitTests` walks every page in every folder for all three. The rest is a review +obligation, and this page says so rather than implying otherwise. ## At your scale - **One page.** `docs/wiki/index.md` plus `Home.md` and `_Sidebar.md`, and a `mkdocs.yml`. Three small files. + No folders, and the sidebar is a flat list. - **A library.** One page per public concern, plus a getting-started page that is the shortest path to a - working example. Keep the consumer contract on its own page — it is the page that must not drift. -- **A platform.** Add a page per subsystem, and keep a single hub that links them all. The hub is what stops - a wiki becoming a search problem. + working example. Add a folder once a topic has two or three pages. Keep the consumer contract on its own + page — it is the page that must not drift. +- **A platform.** One folder per subsystem, and a single hub that links them all, grouped by the same + sections the sidebar uses. The hub is what stops a wiki becoming a search problem. - **Several repositories.** Keep each wiki with its code, and let one site aggregate them. The aggregation is a build concern; ownership stays with the repository. ## See also -- [Home](Home.md) -- [Agent Enablement](Agent-Enablement.md) -- [Contributing](Contributing.md) +- [Home](../Home.md) +- [Agent Enablement](../agents/Agent-Enablement.md) +- [Contributing](../governance/Contributing.md) diff --git a/docs/wiki/Project-Responsibilities.md b/docs/wiki/foundations/Project-Responsibilities.md similarity index 97% rename from docs/wiki/Project-Responsibilities.md rename to docs/wiki/foundations/Project-Responsibilities.md index db177f7..9f782de 100644 --- a/docs/wiki/Project-Responsibilities.md +++ b/docs/wiki/foundations/Project-Responsibilities.md @@ -289,8 +289,8 @@ stops an API startup path from mutating a production schema. Persistence also owns the `DbContext`, the mappings and the identifier strategy's model wiring; the provider choice belongs where the context is registered, usually Composition or the host. Core and -Application never see EF Core. [EF Core Integration](EF-Core-Integration.md) states the rules that keep -that boundary honest, and [GUID Key Strategy](Guid-Key-Strategy.md) owns the identifier-specific part. +Application never see EF Core. [EF Core Integration](../data/EF-Core-Integration.md) states the rules that keep +that boundary honest, and [GUID Key Strategy](../data/Guid-Key-Strategy.md) owns the identifier-specific part. ### Diagram G — persistence and migration @@ -464,7 +464,7 @@ flowchart TD ## See also - [Architecture as Tests](Architecture-As-Tests.md) — how a dependency rule becomes a failing build -- [EF Core Integration](EF-Core-Integration.md) — what the Persistence project owns +- [EF Core Integration](../data/EF-Core-Integration.md) — what the Persistence project owns - [Repository Shape](Repository-Shape.md) -- [Engineering Principles](Engineering-Principles.md) -- [Adopting This at Your Scale](Adopting-This-At-Your-Scale.md) +- [Engineering Principles](../Engineering-Principles.md) +- [Adopting This at Your Scale](../governance/Adopting-This-At-Your-Scale.md) diff --git a/docs/wiki/Repository-Shape.md b/docs/wiki/foundations/Repository-Shape.md similarity index 98% rename from docs/wiki/Repository-Shape.md rename to docs/wiki/foundations/Repository-Shape.md index c791939..9b79e12 100644 --- a/docs/wiki/Repository-Shape.md +++ b/docs/wiki/foundations/Repository-Shape.md @@ -43,7 +43,7 @@ Repository/ `artifacts/`, `.tools/` and `TestResults/` are generated and gitignored; they are in the layout above only so that seeing them is not a surprise. -Not every file above is created by [Getting Started](Getting-Started.md), and the difference is worth +Not every file above is created by [Getting Started](../Getting-Started.md), and the difference is worth knowing before you follow it expecting a finished repository: | File | Where it comes from | @@ -210,7 +210,7 @@ directories. ## See also -- [Getting Started](Getting-Started.md) +- [Getting Started](../Getting-Started.md) - [Architecture as Tests](Architecture-As-Tests.md) - [Documentation Convention](Documentation-Convention.md) -- [Agent Enablement](Agent-Enablement.md) +- [Agent Enablement](../agents/Agent-Enablement.md) diff --git a/docs/wiki/Verification-Model.md b/docs/wiki/foundations/Verification-Model.md similarity index 97% rename from docs/wiki/Verification-Model.md rename to docs/wiki/foundations/Verification-Model.md index 2a46ac9..1ee0019 100644 --- a/docs/wiki/Verification-Model.md +++ b/docs/wiki/foundations/Verification-Model.md @@ -117,7 +117,7 @@ A BDTest acceptance suite is a slow tier of this kind, with one addition: the jo in that shape at all. A container-backed suite adds a different one: pin the backend with `PURVIEW_CONTAINERS_BACKEND` in the job, so a runner without that runtime fails the job rather than skipping every test and reporting green. Both are covered in [Testing and Test -Data](Testing-And-Test-Data.md). +Data](../testing/Testing-And-Test-Data.md). ## The configuration file @@ -160,7 +160,7 @@ The repository also owns a runnable sample, `samples/Acme.Persistence`, that the build. It sits outside `src/`, has no analyzers and is not in the canonical solution; `just samples` is its verification, and it fails with a non-zero exit code when its identifier or model checks are untrue. That is a deliberate fourth tier — a sample, not a test — and the page says so rather than counting it in -the fast job. [EF Core Integration](EF-Core-Integration.md) lists the checks the sample and an adopting +the fast job. [EF Core Integration](../data/EF-Core-Integration.md) lists the checks the sample and an adopting repository's integration suite should cover. ## A gate is not bypassed @@ -229,8 +229,8 @@ ten minutes. ## See also -- [Release Flow](Release-Flow.md) -- [Testing and Test Data](Testing-And-Test-Data.md) +- [Release Flow](../governance/Release-Flow.md) +- [Testing and Test Data](../testing/Testing-And-Test-Data.md) - [Architecture as Tests](Architecture-As-Tests.md) - [build: Configuration Reference](https://github.com/purview-dev/build/blob/main/docs/wiki/Configuration-Reference.md) diff --git a/docs/wiki/Adopting-This-At-Your-Scale.md b/docs/wiki/governance/Adopting-This-At-Your-Scale.md similarity index 92% rename from docs/wiki/Adopting-This-At-Your-Scale.md rename to docs/wiki/governance/Adopting-This-At-Your-Scale.md index 86df6c2..5961b27 100644 --- a/docs/wiki/Adopting-This-At-Your-Scale.md +++ b/docs/wiki/governance/Adopting-This-At-Your-Scale.md @@ -66,7 +66,7 @@ Skip: Everything from Small, plus: -- **Architecture tests.** Rules 1–3 from [Architecture as Tests](Architecture-As-Tests.md). A page of code, +- **Architecture tests.** Rules 1–3 from [Architecture as Tests](../foundations/Architecture-As-Tests.md). A page of code, and it pays for itself the first time someone adds a reference "just to reuse a helper". - **A shared testing project.** Once two test projects need the same builder or fixture, `SharedTestingInfra` gives them one home and the SDK references it automatically. @@ -76,7 +76,7 @@ Everything from Small, plus: example. - **The EF Core integration rules as soon as persistence exists.** A `Persistence` project, value objects mapped once, design-time and runtime options in step, and a real-store integration suite. See - [EF Core Integration](EF-Core-Integration.md). + [EF Core Integration](../data/EF-Core-Integration.md). This is the profile the reference implementation in this repository is built to. It is the smallest shape where every mechanism in the playbook is visible. @@ -93,8 +93,8 @@ Everything from Medium, plus: - **A release gate.** The slow tier runs before a release, not only on a pull request. - **Release channels** rather than a second repository for prereleases. - **The derived-identifier catalogue and the two-provider GUID strategy**, once a system tenant or a - second store appears. See [Well-Known Identifiers](Well-Known-Identifiers.md) and [GUID Key - Strategy](Guid-Key-Strategy.md). + second store appears. See [Well-Known Identifiers](../data/Well-Known-Identifiers.md) and [GUID Key + Strategy](../data/Guid-Key-Strategy.md). - **Your own agent skills**, packaged so the guidance travels with the code. - **Architecture rules promoted into the build.** At this size a rule that can be skipped is a rule that will be, so move it from a test into an analyzer or an MSBuild check that runs before compile. @@ -110,7 +110,7 @@ tests are ceremony. **A GUID strategy before the second provider.** With one store and moderate write volume, a store default or `Guid.NewGuid()` is enough. The strategy witness, options extension and model-finalising convention earn their place when a second provider exists or the identifier must be known before `SaveChanges` — -not in anticipation. See [GUID Key Strategy](Guid-Key-Strategy.md). +not in anticipation. See [GUID Key Strategy](../data/Guid-Key-Strategy.md). **A test data builder after the tests.** Retrofitting `TestBuilder` means editing every test file at once, which means a large diff nobody reviews carefully. Adopt it with the first test, when the diff is one file. @@ -145,11 +145,11 @@ where it belongs. A migration that leaves the conventions undocumented is a migr ## See also -- [Getting Started](Getting-Started.md) — the same steps, in order, with the files inline +- [Getting Started](../Getting-Started.md) — the same steps, in order, with the files inline - [Templates](https://github.com/purview-dev/engineering-playbook/tree/main/templates) — the copy-paste versions -- [Engineering Principles](Engineering-Principles.md) -- [EF Core Integration](EF-Core-Integration.md) -- [Well-Known Identifiers](Well-Known-Identifiers.md) -- [GUID Key Strategy](Guid-Key-Strategy.md) -- [Worked Examples](Worked-Examples.md) +- [Engineering Principles](../Engineering-Principles.md) +- [EF Core Integration](../data/EF-Core-Integration.md) +- [Well-Known Identifiers](../data/Well-Known-Identifiers.md) +- [GUID Key Strategy](../data/Guid-Key-Strategy.md) +- [Worked Examples](../examples/Worked-Examples.md) - [Contributing](Contributing.md) diff --git a/docs/wiki/Contributing.md b/docs/wiki/governance/Contributing.md similarity index 88% rename from docs/wiki/Contributing.md rename to docs/wiki/governance/Contributing.md index 5fa649c..a77e190 100644 --- a/docs/wiki/Contributing.md +++ b/docs/wiki/governance/Contributing.md @@ -31,12 +31,15 @@ because people rely on the guarantee and stop looking. Each criterion removes on ## Adding a page -1. **Write the page** in `docs/wiki/.md`. Title case, hyphens between words. -2. **Follow the four sections** from [Documentation Convention](Documentation-Convention.md): the rule, why, +1. **Write the page** in `docs/wiki/
/.md`. Use the topic folder for its section, a + title-case file name, and hyphens between words. A page that belongs to no existing section needs a new + folder, added to both `_Sidebar.md` and `Home.md`. +2. **Follow the four sections** from [Documentation Convention](../foundations/Documentation-Convention.md): the rule, why, how it is enforced, at your scale. -3. **Add it to `_Sidebar.md`.** A page that is not in the navigation is a page nobody finds. -4. **Add it to the table in `Home.md`.** The hub is how a reader discovers a page they did not know to look - for. +3. **Add it to `_Sidebar.md`** under the matching section. A page that is not in the navigation is a page + nobody finds. +4. **Add it to the matching table in `Home.md`.** The hub is how a reader discovers a page they did not know + to look for, and the section it uses must match the sidebar label. 5. **Link both ways.** A page with no inbound link is a page that will be deleted by accident; a page with no outbound links is a dead end. 6. **Link to the authority, and name the evidence.** Where a rule is the SDK's, link to the SDK's page. Where @@ -115,7 +118,7 @@ checks in [Validation before handing work back](#validation-before-handing-work- ## See also -- [Documentation Convention](Documentation-Convention.md) -- [Engineering Principles](Engineering-Principles.md) +- [Documentation Convention](../foundations/Documentation-Convention.md) +- [Engineering Principles](../Engineering-Principles.md) - [Adopting This at Your Scale](Adopting-This-At-Your-Scale.md) - [Release Flow](Release-Flow.md) diff --git a/docs/wiki/Cross-Repository-Harvest.md b/docs/wiki/governance/Cross-Repository-Harvest.md similarity index 93% rename from docs/wiki/Cross-Repository-Harvest.md rename to docs/wiki/governance/Cross-Repository-Harvest.md index d0e18d2..dcb06c2 100644 --- a/docs/wiki/Cross-Repository-Harvest.md +++ b/docs/wiki/governance/Cross-Repository-Harvest.md @@ -49,8 +49,8 @@ symptom was one extra hop nobody could see. This page's repository-name test was exactly that, and the correction to `Home.md` ships with it — a test with nothing to fail on is a test nobody believes. -**A claim three pages agree on has not been checked.** `AGENTS.md`, `Agent-Enablement.md` and -`Repository-Shape.md` all stated that `.agents/skills/` is gitignored. `git check-ignore +**A claim three pages agree on has not been checked.** `AGENTS.md`, `agents/Agent-Enablement.md` and +`foundations/Repository-Shape.md` all stated that `.agents/skills/` is gitignored. `git check-ignore .agents/skills/x/SKILL.md` exits 1, and the SDK's own `.gitignore` template carries no such line: the rule was stated in three places and existed in none. Repetition reads as verification, which is why a harvest records a SHA rather than an impression. The rule is now in `.gitignore`, so the three pages @@ -67,7 +67,7 @@ other's question produces an answer with a citation that does not support it. ## Deviations the first harvest found -The [Documentation Convention](Documentation-Convention.md) says a wiki lives in `docs/wiki`. Of the +The [Documentation Convention](../foundations/Documentation-Convention.md) says a wiki lives in `docs/wiki`. Of the sixteen public repositories, twelve do. `architests`, `value-objects` and `purview-dev.github.io` publish from `docs`, and `pm-skills` publishes no documentation folder at all, documenting itself through its fourteen skills. @@ -129,8 +129,8 @@ behind its tip. Regenerating the snapshot is part of merging a harvest, not part ## See also -- [Documentation Convention](Documentation-Convention.md) — where a page lives, and why ownership is +- [Documentation Convention](../foundations/Documentation-Convention.md) — where a page lives, and why ownership is the rule rather than the folder name -- [Agent Skills Distribution](Agent-Skills-Distribution.md) — how a skill reaches a consumer -- [Engineering Principles](Engineering-Principles.md) — the rules a harvest most often finds behind +- [Agent Skills Distribution](../agents/Agent-Skills-Distribution.md) — how a skill reaches a consumer +- [Engineering Principles](../Engineering-Principles.md) — the rules a harvest most often finds behind - [Adopting This at Your Scale](Adopting-This-At-Your-Scale.md) diff --git a/docs/wiki/Release-Flow.md b/docs/wiki/governance/Release-Flow.md similarity index 98% rename from docs/wiki/Release-Flow.md rename to docs/wiki/governance/Release-Flow.md index 7e3a8a8..edb7d39 100644 --- a/docs/wiki/Release-Flow.md +++ b/docs/wiki/governance/Release-Flow.md @@ -184,7 +184,7 @@ have done. ## See also -- [Verification Model](Verification-Model.md) -- [Engineering Principles](Engineering-Principles.md) +- [Verification Model](../foundations/Verification-Model.md) +- [Engineering Principles](../Engineering-Principles.md) - [build: Release Flow](https://github.com/purview-dev/build/blob/main/docs/wiki/Release-Flow.md) - [build: Release Models](https://github.com/purview-dev/build/blob/main/docs/wiki/Release-Models.md) diff --git a/docs/wiki/Testing-And-Test-Data.md b/docs/wiki/testing/Testing-And-Test-Data.md similarity index 98% rename from docs/wiki/Testing-And-Test-Data.md rename to docs/wiki/testing/Testing-And-Test-Data.md index 7bd22b0..b7df7e7 100644 --- a/docs/wiki/Testing-And-Test-Data.md +++ b/docs/wiki/testing/Testing-And-Test-Data.md @@ -444,7 +444,7 @@ Three rules make such a suite safe to own: - **It lives in its own `.IntegrationTests` project.** The tier comes from the name, which keeps it out of the pull-request filter without anybody remembering an attribute. See - [Verification Model](Verification-Model.md). + [Verification Model](../foundations/Verification-Model.md). - **It skips locally when no backend is usable, and fails in CI.** Those are two different situations and must not share an outcome. Locally, probe and skip; in CI, pin the backend with `PURVIEW_CONTAINERS_BACKEND`, because a named backend never falls back, so an unavailable runtime fails @@ -471,7 +471,7 @@ no persistence and its pipeline runs the `[Category=Unit]` tier only. `samples/A EF Core side — a real provider when given a connection string, in-memory only for the runnable default — but it is a console self-check rather than a test project, and `just samples` is its check. [containers](https://github.com/purview-dev/containers) is the repository to read for the second-job -pattern in use, and [EF Core Integration](EF-Core-Integration.md) states the rules a container-backed suite +pattern in use, and [EF Core Integration](../data/EF-Core-Integration.md) states the rules a container-backed suite should prove. ## How it is enforced @@ -507,14 +507,14 @@ should prove. repository with no such audience should keep writing unit tests. Reach for the HTML report only once somebody is actually going to read it. - **A package with a documented contract.** Add the consumer-verification script described in - [Engineering Principles](Engineering-Principles.md). + [Engineering Principles](../Engineering-Principles.md). ## See also -- [Verification Model](Verification-Model.md) -- [Architecture as Tests](Architecture-As-Tests.md) -- [EF Core Integration](EF-Core-Integration.md) -- [Worked Examples](Worked-Examples.md) +- [Verification Model](../foundations/Verification-Model.md) +- [Architecture as Tests](../foundations/Architecture-As-Tests.md) +- [EF Core Integration](../data/EF-Core-Integration.md) +- [Worked Examples](../examples/Worked-Examples.md) - [BDTest](https://bdtest.tomlonghurst.dev/) - [Purview.Containers](https://purview.dev/docs/containers/) - [build-sdk: Testing diff --git a/skills/purview-architecture-testing/SKILL.md b/skills/purview-architecture-testing/SKILL.md index 208b5e2..55d0ca8 100644 --- a/skills/purview-architecture-testing/SKILL.md +++ b/skills/purview-architecture-testing/SKILL.md @@ -84,7 +84,7 @@ debugging the package. Then add a test that the documentation matches the policy, so the table in the wiki is falsifiable too. Full worked example: -[Project Responsibilities](https://github.com/purview-dev/engineering-playbook/blob/main/docs/wiki/Project-Responsibilities.md). +[Project Responsibilities](https://github.com/purview-dev/engineering-playbook/blob/main/docs/wiki/foundations/Project-Responsibilities.md). ## 3. Read project files, and assemblies @@ -181,4 +181,4 @@ project classified so every dependency rule still applies to it. Prefer a waiver - `purview-architecture` — what the projects are for, and how they are named - `purview-buildsdk-architecture-tests` — the package's own skill, authoritative on its API -- [Architecture as Tests](https://github.com/purview-dev/engineering-playbook/blob/main/docs/wiki/Architecture-As-Tests.md) +- [Architecture as Tests](https://github.com/purview-dev/engineering-playbook/blob/main/docs/wiki/foundations/Architecture-As-Tests.md) diff --git a/skills/purview-architecture/SKILL.md b/skills/purview-architecture/SKILL.md index 8e76628..0c43596 100644 --- a/skills/purview-architecture/SKILL.md +++ b/skills/purview-architecture/SKILL.md @@ -174,4 +174,4 @@ small telemetry — it does not get none. See `purview-telemetry`. - `purview-telemetry` — instrumentation at every scale - `purview-persistence` — storage and GUID-key guidance, only when persistence is real - [Engineering Principles](https://github.com/purview-dev/engineering-playbook/blob/main/docs/wiki/Engineering-Principles.md) -- [Adopting This At Your Scale](https://github.com/purview-dev/engineering-playbook/blob/main/docs/wiki/Adopting-This-At-Your-Scale.md) +- [Adopting This At Your Scale](https://github.com/purview-dev/engineering-playbook/blob/main/docs/wiki/governance/Adopting-This-At-Your-Scale.md) diff --git a/skills/purview-architecture/references/contract-strategy.md b/skills/purview-architecture/references/contract-strategy.md index e281a41..62b5a17 100644 --- a/skills/purview-architecture/references/contract-strategy.md +++ b/skills/purview-architecture/references/contract-strategy.md @@ -230,7 +230,7 @@ combines" stays a review obligation, because a dependency matrix cannot express ## See also -- [Contracts and Data Exchange](https://github.com/purview-dev/engineering-playbook/blob/main/docs/wiki/Contracts-And-Data-Exchange.md) +- [Contracts and Data Exchange](https://github.com/purview-dev/engineering-playbook/blob/main/docs/wiki/data/Contracts-And-Data-Exchange.md) — `Create` and `Hydrate`, and the schema as the source of truth for a wire shape - [zodsharp](https://github.com/purview-dev/zodsharp) — authoritative on `[ZodSchema]` and JSON Schema export diff --git a/skills/purview-architecture/references/project-responsibilities.md b/skills/purview-architecture/references/project-responsibilities.md index d74d2cf..dc4e67c 100644 --- a/skills/purview-architecture/references/project-responsibilities.md +++ b/skills/purview-architecture/references/project-responsibilities.md @@ -3,7 +3,7 @@ The catalogue in brief. The authoritative definition is [`.config/architecture-policy.json`](https://github.com/purview-dev/engineering-playbook/blob/main/.config/architecture-policy.json), and the full page — with diagrams — is -[Project Responsibilities](https://github.com/purview-dev/engineering-playbook/blob/main/docs/wiki/Project-Responsibilities.md). +[Project Responsibilities](https://github.com/purview-dev/engineering-playbook/blob/main/docs/wiki/foundations/Project-Responsibilities.md). Do not restate either here or in another skill; link to them. ## The catalogue diff --git a/src/src/Domain/VerificationTier.cs b/src/src/Domain/VerificationTier.cs index 690cff9..d31dcdf 100644 --- a/src/src/Domain/VerificationTier.cs +++ b/src/src/Domain/VerificationTier.cs @@ -7,7 +7,7 @@ namespace Purview.EngineeringPlaybook.Domain; /// The tier is part of the convention's identity because it decides where the convention is allowed to /// fail: a rule has to be fast and deterministic enough to run on every commit, /// while an rule may need a real external resource and is therefore selected -/// rather than assumed. See docs/wiki/Verification-Model.md. +/// rather than assumed. See docs/wiki/foundations/Verification-Model.md. /// public enum VerificationTier { diff --git a/src/src/Infrastructure/Infrastructure.csproj b/src/src/Infrastructure/Infrastructure.csproj index ba8a826..3b841a8 100644 --- a/src/src/Infrastructure/Infrastructure.csproj +++ b/src/src/Infrastructure/Infrastructure.csproj @@ -6,7 +6,7 @@ This project keeps its own namespace only because src/Directory.Build.props removes `Infrastructure` from the SDK's `NamespaceRemoveSuffix` list. Without that line the SDK would - fold the types into `Purview.EngineeringPlaybook`. See docs/wiki/Repository-Shape.md. + fold the types into `Purview.EngineeringPlaybook`. See docs/wiki/foundations/Repository-Shape.md. --> diff --git a/src/tests/Architecture.UnitTests/ArchitectureTests.cs b/src/tests/Architecture.UnitTests/ArchitectureTests.cs index 8fae65a..2c3c8e3 100644 --- a/src/tests/Architecture.UnitTests/ArchitectureTests.cs +++ b/src/tests/Architecture.UnitTests/ArchitectureTests.cs @@ -20,7 +20,7 @@ namespace Purview.EngineeringPlaybook.Architecture; /// /// stays hand-written and separate: it reads compiled assembly /// metadata, which catches a dependency that arrived indirectly and which the policy graph - built -/// from declared ProjectReferences - cannot see. See docs/wiki/Architecture-As-Tests.md. +/// from declared ProjectReferences - cannot see. See docs/wiki/foundations/Architecture-As-Tests.md. /// /// [InheritsTests] diff --git a/src/tests/Architecture.UnitTests/DependencyDirectionTests.cs b/src/tests/Architecture.UnitTests/DependencyDirectionTests.cs index 72909be..3dfce02 100644 --- a/src/tests/Architecture.UnitTests/DependencyDirectionTests.cs +++ b/src/tests/Architecture.UnitTests/DependencyDirectionTests.cs @@ -13,7 +13,7 @@ namespace Purview.EngineeringPlaybook.Architecture; /// /// These are the rules a diagram cannot keep true. Each one reads the compiled assemblies and their /// metadata references, so a ProjectReference that points the wrong way fails the build rather than -/// being noticed in review. See docs/wiki/Architecture-As-Tests.md. +/// being noticed in review. See docs/wiki/foundations/Architecture-As-Tests.md. /// public sealed class DependencyDirectionTests { diff --git a/src/tests/Architecture.UnitTests/PolicyDocumentationTests.cs b/src/tests/Architecture.UnitTests/PolicyDocumentationTests.cs index c462e9d..2709d51 100644 --- a/src/tests/Architecture.UnitTests/PolicyDocumentationTests.cs +++ b/src/tests/Architecture.UnitTests/PolicyDocumentationTests.cs @@ -10,14 +10,14 @@ namespace Purview.EngineeringPlaybook.Architecture; /// The policy is stated twice by necessity - once as JSON the tests evaluate, once as a table a human /// reads. Two statements of one rule drift, and the prose is the copy that drifts silently, because /// nothing fails when it is wrong. These tests make the documentation falsifiable. -/// See docs/wiki/Project-Responsibilities.md. +/// See docs/wiki/foundations/Project-Responsibilities.md. /// public sealed partial class PolicyDocumentationTests { static readonly ArchitecturePolicy Policy = ArchitecturePolicy.Load(); static string DocumentationPath => - Path.Combine(ArchitecturePolicy.RepositoryRoot(), "docs", "wiki", "Project-Responsibilities.md"); + Path.Combine(ArchitecturePolicy.RepositoryRoot(), "docs", "wiki", "foundations", "Project-Responsibilities.md"); /// Reads the responsibilities page. /// Cancels the read. @@ -25,7 +25,7 @@ public sealed partial class PolicyDocumentationTests /// /// A method rather than a property, because a property cannot be async and a synchronous one /// would hide File.ReadAllText from VSTHRD103 - the analyzer only sees a synchronous - /// call when it sits inside a Task-returning method. See docs/wiki/Testing-And-Test-Data.md. + /// call when it sits inside a Task-returning method. See docs/wiki/testing/Testing-And-Test-Data.md. /// static async Task ReadDocumentationAsync(CancellationToken cancellationToken) => await File.ReadAllTextAsync(DocumentationPath, cancellationToken); @@ -113,7 +113,7 @@ CancellationToken cancellationToken { mismatches.Add( $"{name}: the page says '{documented}' but the policy says '{expected}'. " - + "Update docs/wiki/Project-Responsibilities.md, or change the policy if the rule moved." + + "Update docs/wiki/foundations/Project-Responsibilities.md, or change the policy if the rule moved." ); } diff --git a/src/tests/Repository.UnitTests/DocumentationTests.cs b/src/tests/Repository.UnitTests/DocumentationTests.cs index 8900809..210f409 100644 --- a/src/tests/Repository.UnitTests/DocumentationTests.cs +++ b/src/tests/Repository.UnitTests/DocumentationTests.cs @@ -3,17 +3,19 @@ namespace Purview.EngineeringPlaybook.Repository; /// -/// Asserts that the wiki obeys the conventions in docs/wiki/Documentation-Convention.md. +/// Asserts that the wiki obeys the conventions in docs/wiki/foundations/Documentation-Convention.md. /// /// /// -/// Two documentation rules are machine-checkable and both break silently: a page that is not in the -/// navigation is a page nobody finds, and a bare code fence renders as an untyped block. The -/// convention page states both; these tests make the statement true rather than aspirational. +/// Three documentation rules are machine-checkable and all break silently: a page that is not in the +/// navigation is a page nobody finds, a link that points at the wrong folder is a 404 nobody sees in +/// review, and a bare code fence renders as an untyped block. The convention page states all three; +/// these tests make the statement true rather than aspirational. /// /// -/// index.md is the landing page rather than a content page, so the navigation checks exclude -/// it; the fence rule applies to every page, including the landing page. +/// The page walk is recursive, so a page in a topic folder is held to the same rules as one at the wiki +/// root. index.md is the landing page rather than a content page, so the navigation checks +/// exclude it; the link and fence rules apply to every page, including the landing page. /// /// public sealed partial class DocumentationTests @@ -21,6 +23,9 @@ public sealed partial class DocumentationTests [GeneratedRegex(@"\]\((?[^)]+)\)")] private static partial Regex LinkPattern(); + [GeneratedRegex(@"^\s*-\s+\*\*(?