feat: define local YAML documentation database
This commit is contained in:
@@ -8,13 +8,14 @@ description: >
|
|||||||
admonitions, editing docusaurus.config.ts, applying voice and inclusive-language standards,
|
admonitions, editing docusaurus.config.ts, applying voice and inclusive-language standards,
|
||||||
or setting up deployment to Vercel, Netlify, GitHub Pages, or Cloudflare Pages. Triggers on
|
or setting up deployment to Vercel, Netlify, GitHub Pages, or Cloudflare Pages. Triggers on
|
||||||
docs/, blog/, docusaurus.config, sidebars.ts, .mdx files, or any request to write, improve,
|
docs/, blog/, docusaurus.config, sidebars.ts, .mdx files, or any request to write, improve,
|
||||||
render editable Draw.io sources with docusaurus-plugin-drawio, or restructure documentation — even when the user only says "write docs", "document this",
|
build a local YAML data database for React/MDX views, render editable Draw.io sources with
|
||||||
|
docusaurus-plugin-drawio, or restructure documentation — even when the user only says "write docs", "document this",
|
||||||
or "the docs are a mess". Asks who the reader is and what they should be able to DO before
|
or "the docs are a mess". Asks who the reader is and what they should be able to DO before
|
||||||
writing, because the answer decides the structure.
|
writing, because the answer decides the structure.
|
||||||
license: MIT
|
license: MIT
|
||||||
metadata:
|
metadata:
|
||||||
author: workspace-skills-code-agent
|
author: workspace-skills-code-agent
|
||||||
version: "1.1"
|
version: "1.2"
|
||||||
spec: agentskills.io/specification
|
spec: agentskills.io/specification
|
||||||
framework: Diátaxis
|
framework: Diátaxis
|
||||||
hermes:
|
hermes:
|
||||||
@@ -129,6 +130,10 @@ Use these replacements. This isn't optional:
|
|||||||
|
|
||||||
## Dynamic Documentation Patterns
|
## Dynamic Documentation Patterns
|
||||||
|
|
||||||
|
### Local YAML data-backed documentation
|
||||||
|
|
||||||
|
When Epics, Features, Tasks, requirements, or architectural decisions must feed several documentation views, keep the authoritative records in a local `.yml`-only data tree and load them during the Docusaurus build. Requirements must use separate functional and non-functional folders, and architectural decisions must use the exact `data/architecture-decisions/` folder. Do not duplicate records inside MDX. Follow [references/local-yaml-data-database.md](references/local-yaml-data-database.md) for record schemas, stable IDs, canonical relationships, generated indexes, validation, React hooks/components, MDX composition, and maintenance commands.
|
||||||
|
|
||||||
### Draw.io source diagrams
|
### Draw.io source diagrams
|
||||||
|
|
||||||
When a page needs a Draw.io diagram, keep the editable `.drawio` XML in the documentation repository and render that source directly with `docusaurus-plugin-drawio`. Load `drawio-main` to author or change the diagram, then follow [references/drawio-source-diagrams.md](references/drawio-source-diagrams.md) to install the plugin with pnpm, register it, consume the source from MDX with `@theme/Drawio` and `!!raw-loader!`, select multi-page diagrams, and verify the production build and browser rendering. An exported PNG/SVG alone is not an onboarded source diagram.
|
When a page needs a Draw.io diagram, keep the editable `.drawio` XML in the documentation repository and render that source directly with `docusaurus-plugin-drawio`. Load `drawio-main` to author or change the diagram, then follow [references/drawio-source-diagrams.md](references/drawio-source-diagrams.md) to install the plugin with pnpm, register it, consume the source from MDX with `@theme/Drawio` and `!!raw-loader!`, select multi-page diagrams, and verify the production build and browser rendering. An exported PNG/SVG alone is not an onboarded source diagram.
|
||||||
@@ -180,6 +185,7 @@ Load the one that matches the task. Don't read all four.
|
|||||||
| Write a page, or decide which quadrant it belongs in | [references/diataxis-patterns.md](references/diataxis-patterns.md) — copy-ready template per quadrant, the decision tree, and how to link between them |
|
| Write a page, or decide which quadrant it belongs in | [references/diataxis-patterns.md](references/diataxis-patterns.md) — copy-ready template per quadrant, the decision tree, and how to link between them |
|
||||||
| Write or edit prose, headings, lists, or code examples | [references/writing-guide.md](references/writing-guide.md) — voice, words to cut, inclusive language, pre-publish checklist |
|
| Write or edit prose, headings, lists, or code examples | [references/writing-guide.md](references/writing-guide.md) — voice, words to cut, inclusive language, pre-publish checklist |
|
||||||
| Touch `docusaurus.config.ts` | [references/config-reference.md](references/config-reference.md) — the options that matter, sensible defaults, config anti-patterns |
|
| Touch `docusaurus.config.ts` | [references/config-reference.md](references/config-reference.md) — the options that matter, sensible defaults, config anti-patterns |
|
||||||
|
| Build or maintain a local YAML database that feeds React components and MDX | [references/local-yaml-data-database.md](references/local-yaml-data-database.md) — dedicated entity folders, `.yml` schemas, indexes, relationships, build-time loading, typed hooks, and validation |
|
||||||
| Onboard or render an editable `.drawio` source | [references/drawio-source-diagrams.md](references/drawio-source-diagrams.md) — pnpm install, plugin registration, MDX raw-source import, viewer options, and verification |
|
| Onboard or render an editable `.drawio` source | [references/drawio-source-diagrams.md](references/drawio-source-diagrams.md) — pnpm install, plugin registration, MDX raw-source import, viewer options, and verification |
|
||||||
| Ship the site, or debug a failing build | [references/deployment.md](references/deployment.md) — Vercel, Netlify, GitHub Pages, Cloudflare, and common failures |
|
| Ship the site, or debug a failing build | [references/deployment.md](references/deployment.md) — Vercel, Netlify, GitHub Pages, Cloudflare, and common failures |
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,394 @@
|
|||||||
|
# Local YAML Data Database
|
||||||
|
|
||||||
|
Use this pattern when structured documentation data must live in the documentation repository, remain reviewable through Git, and drive React components and MDX pages without duplicating entity content inside MDX.
|
||||||
|
|
||||||
|
## Contract
|
||||||
|
|
||||||
|
The source database is a local `data/` tree. It is not a runtime service and it is not a collection of generated MDX pages.
|
||||||
|
|
||||||
|
- Every database source file uses the `.yml` extension.
|
||||||
|
- Keep one record per file.
|
||||||
|
- Keep one `index.yml` in every leaf collection.
|
||||||
|
- Requirements live only under dedicated requirement folders.
|
||||||
|
- Architectural decisions live under the exact folder `data/architecture-decisions/`.
|
||||||
|
- Stable IDs, not titles or paths, define relationships.
|
||||||
|
- Load and validate data during the Docusaurus build-time phase.
|
||||||
|
- React components consume typed build data; they do not read the filesystem in the browser.
|
||||||
|
- MDX composes components and explanatory prose; it does not duplicate structured record content.
|
||||||
|
|
||||||
|
A JSON module created by Docusaurus inside `.docusaurus/` is an allowed generated build artifact. It is not a maintained database source and must not be committed as authoritative data.
|
||||||
|
|
||||||
|
## Required structure
|
||||||
|
|
||||||
|
```text
|
||||||
|
data/
|
||||||
|
├── database.yml
|
||||||
|
├── epics/
|
||||||
|
│ ├── index.yml
|
||||||
|
│ └── epic-001.yml
|
||||||
|
├── features/
|
||||||
|
│ ├── index.yml
|
||||||
|
│ └── feature-001.yml
|
||||||
|
├── tasks/
|
||||||
|
│ ├── index.yml
|
||||||
|
│ └── task-001.yml
|
||||||
|
├── requirements/
|
||||||
|
│ ├── functional/
|
||||||
|
│ │ ├── index.yml
|
||||||
|
│ │ └── fr-001.yml
|
||||||
|
│ └── non-functional/
|
||||||
|
│ ├── index.yml
|
||||||
|
│ └── nfr-001.yml
|
||||||
|
├── architecture-decisions/
|
||||||
|
│ ├── index.yml
|
||||||
|
│ └── adr-001.yml
|
||||||
|
└── indexes/
|
||||||
|
├── epic-features.yml
|
||||||
|
├── feature-tasks.yml
|
||||||
|
├── feature-requirements.yml
|
||||||
|
└── feature-architecture-decisions.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not combine functional requirements, non-functional requirements, architectural decisions, or delivery entities into one catch-all collection. Do not create a generic decision folder. The explicit folders are part of the data contract.
|
||||||
|
|
||||||
|
`database.yml` declares the database schema version and enabled collections:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
schema_version: 1
|
||||||
|
collections:
|
||||||
|
- epics
|
||||||
|
- features
|
||||||
|
- tasks
|
||||||
|
- requirements/functional
|
||||||
|
- requirements/non-functional
|
||||||
|
- architecture-decisions
|
||||||
|
```
|
||||||
|
|
||||||
|
## Stable identifiers and filenames
|
||||||
|
|
||||||
|
Use lowercase stable IDs with a type prefix and numeric sequence:
|
||||||
|
|
||||||
|
| Entity | ID example | Filename |
|
||||||
|
|---|---|---|
|
||||||
|
| Epic | `epic-001` | `epic-001.yml` |
|
||||||
|
| Feature | `feature-001` | `feature-001.yml` |
|
||||||
|
| Functional requirement | `fr-001` | `fr-001.yml` |
|
||||||
|
| Non-functional requirement | `nfr-001` | `nfr-001.yml` |
|
||||||
|
| Task | `task-001` | `task-001.yml` |
|
||||||
|
| Architectural decision | `adr-001` | `adr-001.yml` |
|
||||||
|
|
||||||
|
The filename stem must equal the record's `id`. Never reuse an ID, even after archiving a record. Renaming a title must not change its ID.
|
||||||
|
|
||||||
|
## Entity records
|
||||||
|
|
||||||
|
### Epic
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
id: epic-001
|
||||||
|
title: Project lifecycle registry
|
||||||
|
status: in-progress
|
||||||
|
summary: >
|
||||||
|
Provide a traceable registry of project lifecycle information.
|
||||||
|
owners:
|
||||||
|
- root-at-skic
|
||||||
|
tags:
|
||||||
|
- governance
|
||||||
|
- lifecycle
|
||||||
|
```
|
||||||
|
|
||||||
|
### Feature
|
||||||
|
|
||||||
|
A Feature belongs to one Epic. The Feature owns that relationship through `epic_id`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
id: feature-001
|
||||||
|
title: Display project lifecycle state
|
||||||
|
status: in-progress
|
||||||
|
epic_id: epic-001
|
||||||
|
summary: >
|
||||||
|
Display the current lifecycle state and supporting evidence.
|
||||||
|
owners:
|
||||||
|
- root-at-skic
|
||||||
|
```
|
||||||
|
|
||||||
|
### Task
|
||||||
|
|
||||||
|
A Task belongs to one Feature. The Task owns that relationship through `feature_id`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
id: task-001
|
||||||
|
title: Implement the lifecycle state component
|
||||||
|
status: in-backlog
|
||||||
|
feature_id: feature-001
|
||||||
|
summary: >
|
||||||
|
Render lifecycle status from the local data source.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Functional requirement
|
||||||
|
|
||||||
|
Functional requirements remain in `data/requirements/functional/`. A requirement owns its many-to-many Feature mapping through `feature_ids`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
id: fr-001
|
||||||
|
type: functional
|
||||||
|
title: Display lifecycle state
|
||||||
|
status: approved
|
||||||
|
statement: >
|
||||||
|
The portal must display the current lifecycle state for every project.
|
||||||
|
feature_ids:
|
||||||
|
- feature-001
|
||||||
|
- feature-004
|
||||||
|
```
|
||||||
|
|
||||||
|
### Non-functional requirement
|
||||||
|
|
||||||
|
Non-functional requirements remain in `data/requirements/non-functional/` and use the same relationship field.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
id: nfr-001
|
||||||
|
type: non-functional
|
||||||
|
category: performance
|
||||||
|
title: Resolve documentation data during the static build
|
||||||
|
status: approved
|
||||||
|
statement: >
|
||||||
|
Documentation pages must not require a runtime database service.
|
||||||
|
feature_ids:
|
||||||
|
- feature-001
|
||||||
|
- feature-002
|
||||||
|
```
|
||||||
|
|
||||||
|
### Architectural decision
|
||||||
|
|
||||||
|
Architectural decisions remain in `data/architecture-decisions/`. A decision owns its many-to-many Feature mapping through `feature_ids`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
id: adr-001
|
||||||
|
title: Use local YAML records for structured documentation
|
||||||
|
status: accepted
|
||||||
|
date: 2026-08-14
|
||||||
|
context: >
|
||||||
|
Structured entities must be reused across several documentation views.
|
||||||
|
decision: >
|
||||||
|
Store authoritative records in local YAML files and resolve them during
|
||||||
|
the static documentation build.
|
||||||
|
consequences:
|
||||||
|
- Documentation changes remain Git-reviewable.
|
||||||
|
- The deployed site does not require a database service.
|
||||||
|
feature_ids:
|
||||||
|
- feature-001
|
||||||
|
- feature-002
|
||||||
|
```
|
||||||
|
|
||||||
|
## Relationship ownership
|
||||||
|
|
||||||
|
Store each relationship in one canonical direction only:
|
||||||
|
|
||||||
|
| Relationship | Cardinality | Canonical owner |
|
||||||
|
|---|---:|---|
|
||||||
|
| Epic to Feature | 1:n | Feature stores `epic_id` |
|
||||||
|
| Feature to Task | 1:n | Task stores `feature_id` |
|
||||||
|
| Requirement to Feature | n:m | Requirement stores `feature_ids` |
|
||||||
|
| Architectural decision to Feature | n:m | Architectural decision stores `feature_ids` |
|
||||||
|
|
||||||
|
Do not also store `feature_ids` on Epics, `task_ids` on Features, or reverse requirement and decision IDs on Features. Generate reverse lookups in `data/indexes/`. This prevents two editable fields from disagreeing about the same relationship.
|
||||||
|
|
||||||
|
## Collection indexes
|
||||||
|
|
||||||
|
Each leaf collection has an `index.yml` containing stable IDs and relative record paths. Sort entries by ID.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
schema_version: 1
|
||||||
|
items:
|
||||||
|
- id: feature-001
|
||||||
|
file: feature-001.yml
|
||||||
|
- id: feature-002
|
||||||
|
file: feature-002.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
Collection indexes are generated and committed. They make reviews explicit and allow tools to discover records without relying on filesystem ordering.
|
||||||
|
|
||||||
|
## Relationship indexes
|
||||||
|
|
||||||
|
Relationship indexes are derived from canonical record fields. For example, `data/indexes/feature-requirements.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
schema_version: 1
|
||||||
|
features:
|
||||||
|
feature-001:
|
||||||
|
functional:
|
||||||
|
- fr-001
|
||||||
|
non_functional:
|
||||||
|
- nfr-001
|
||||||
|
feature-002:
|
||||||
|
functional: []
|
||||||
|
non_functional:
|
||||||
|
- nfr-001
|
||||||
|
```
|
||||||
|
|
||||||
|
And `data/indexes/feature-architecture-decisions.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
schema_version: 1
|
||||||
|
features:
|
||||||
|
feature-001:
|
||||||
|
architecture_decisions:
|
||||||
|
- adr-001
|
||||||
|
feature-002:
|
||||||
|
architecture_decisions:
|
||||||
|
- adr-001
|
||||||
|
```
|
||||||
|
|
||||||
|
Never edit derived relationship indexes manually. Regenerate them from source records.
|
||||||
|
|
||||||
|
## Maintenance commands
|
||||||
|
|
||||||
|
Every adopting documentation repository must expose these commands:
|
||||||
|
|
||||||
|
```text
|
||||||
|
pnpm data:index
|
||||||
|
pnpm data:validate
|
||||||
|
pnpm data:check
|
||||||
|
```
|
||||||
|
|
||||||
|
- `pnpm data:index` deterministically rebuilds collection and relationship indexes.
|
||||||
|
- `pnpm data:validate` validates schemas, IDs, files, and relationship integrity.
|
||||||
|
- `pnpm data:check` regenerates indexes in memory or a temporary directory and fails when committed indexes are stale.
|
||||||
|
|
||||||
|
Index generation must not add timestamps or machine-specific paths. Running it twice against unchanged records must produce byte-identical output.
|
||||||
|
|
||||||
|
## Validation requirements
|
||||||
|
|
||||||
|
Validation must fail for:
|
||||||
|
|
||||||
|
- any source database file whose extension is not `.yml`;
|
||||||
|
- a missing collection `index.yml`;
|
||||||
|
- a duplicate record ID;
|
||||||
|
- a filename stem that differs from the record ID;
|
||||||
|
- an unknown entity type, status, or requirement category;
|
||||||
|
- a required field with an empty value;
|
||||||
|
- a dangling `epic_id`, `feature_id`, or entry in `feature_ids`;
|
||||||
|
- an index entry whose record is missing;
|
||||||
|
- a record missing from its collection index;
|
||||||
|
- a stale relationship index;
|
||||||
|
- a record placed in the wrong collection;
|
||||||
|
- an architectural decision outside `data/architecture-decisions/`;
|
||||||
|
- a functional or non-functional requirement outside its dedicated folder.
|
||||||
|
|
||||||
|
Run validation before the Docusaurus build and in Gitea Actions. A successful site build is not sufficient if data validation was skipped.
|
||||||
|
|
||||||
|
## Docusaurus build-time loading
|
||||||
|
|
||||||
|
Browsers cannot safely discover repository files at runtime. Implement a local Docusaurus plugin that:
|
||||||
|
|
||||||
|
1. reads `data/database.yml` and all collection indexes;
|
||||||
|
2. parses the referenced `.yml` records;
|
||||||
|
3. validates records and relationships;
|
||||||
|
4. constructs typed entity maps and reverse indexes;
|
||||||
|
5. publishes one immutable client data module with `actions.createData`;
|
||||||
|
6. optionally registers generic routes for entity details and traceability views.
|
||||||
|
|
||||||
|
Keep parsing, validation, and relationship resolution on the Node build side. Do not bundle filesystem APIs or independent YAML parsers into each React component.
|
||||||
|
|
||||||
|
A minimal plugin shape is:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export default function localYamlDataPlugin() {
|
||||||
|
return {
|
||||||
|
name: 'local-yaml-data',
|
||||||
|
|
||||||
|
async loadContent() {
|
||||||
|
return loadAndValidateDatabase('data');
|
||||||
|
},
|
||||||
|
|
||||||
|
async contentLoaded({content, actions}) {
|
||||||
|
await actions.createData(
|
||||||
|
'documentation-database.json',
|
||||||
|
JSON.stringify(content),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Treat the generated module as derived data. Rebuild it from the YAML source on every production build.
|
||||||
|
|
||||||
|
## Typed React access
|
||||||
|
|
||||||
|
Provide one data context and stable hooks rather than letting components know storage paths:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const epic = useEpic('epic-001');
|
||||||
|
const features = useFeaturesForEpic('epic-001');
|
||||||
|
const tasks = useTasksForFeature('feature-001');
|
||||||
|
const requirements = useRequirementsForFeature('feature-001');
|
||||||
|
const decisions = useArchitectureDecisionsForFeature('feature-001');
|
||||||
|
const traceability = useFeatureTraceability('feature-001');
|
||||||
|
```
|
||||||
|
|
||||||
|
Recommended components:
|
||||||
|
|
||||||
|
- `EpicTree`
|
||||||
|
- `EpicDetails`
|
||||||
|
- `FeatureDetails`
|
||||||
|
- `FeatureTasks`
|
||||||
|
- `RequirementDetails`
|
||||||
|
- `RequirementsForFeature`
|
||||||
|
- `ArchitectureDecisionDetails`
|
||||||
|
- `ArchitectureDecisionsForFeature`
|
||||||
|
- `RequirementFeatureMatrix`
|
||||||
|
- `DecisionFeatureMatrix`
|
||||||
|
- `TraceabilityMatrix`
|
||||||
|
|
||||||
|
Components receive stable IDs or filter properties. They must render a clear missing-record state rather than silently returning empty output.
|
||||||
|
|
||||||
|
## MDX composition
|
||||||
|
|
||||||
|
MDX pages provide page purpose, explanation, and component placement. They must not copy record fields that already exist in the database.
|
||||||
|
|
||||||
|
```mdx
|
||||||
|
---
|
||||||
|
title: "Explore delivery scope"
|
||||||
|
description: "Inspect Epics, Features, Tasks, requirements, and decisions."
|
||||||
|
---
|
||||||
|
|
||||||
|
import EpicTree from '@site/src/components/documentation-data/EpicTree';
|
||||||
|
import TraceabilityMatrix from '@site/src/components/documentation-data/TraceabilityMatrix';
|
||||||
|
|
||||||
|
<EpicTree />
|
||||||
|
|
||||||
|
<TraceabilityMatrix />
|
||||||
|
```
|
||||||
|
|
||||||
|
Use a generic `FeatureDetails` component or generated route for individual Features instead of generating and maintaining one content-heavy MDX file per Feature.
|
||||||
|
|
||||||
|
## Change workflow
|
||||||
|
|
||||||
|
For every data change:
|
||||||
|
|
||||||
|
1. Add or edit the authoritative record in its dedicated folder.
|
||||||
|
2. Preserve existing stable IDs.
|
||||||
|
3. Run `pnpm data:index`.
|
||||||
|
4. Review source and derived index changes together.
|
||||||
|
5. Run `pnpm data:validate`.
|
||||||
|
6. Run `pnpm data:check`.
|
||||||
|
7. Run the Docusaurus typecheck and production build.
|
||||||
|
8. Exercise the affected React view in a browser.
|
||||||
|
9. Commit records and indexes together.
|
||||||
|
10. Verify the Gitea Actions run and deployed documentation route.
|
||||||
|
|
||||||
|
For schema evolution, increment `schema_version`, migrate all records and indexes atomically, and keep the loader's error message explicit about unsupported versions.
|
||||||
|
|
||||||
|
## Acceptance checklist
|
||||||
|
|
||||||
|
- [ ] Database source uses only `.yml` files.
|
||||||
|
- [ ] Requirements are separated into functional and non-functional folders.
|
||||||
|
- [ ] Architectural decisions use exactly `data/architecture-decisions/`.
|
||||||
|
- [ ] Every entity has one stable-ID record file.
|
||||||
|
- [ ] Every leaf collection has a deterministic `index.yml`.
|
||||||
|
- [ ] Canonical relationship fields implement Epic → Feature → Task and n:m mappings to requirements and architectural decisions.
|
||||||
|
- [ ] Reverse indexes are generated, committed, and stale-index checked.
|
||||||
|
- [ ] Referential validation rejects duplicate and dangling IDs.
|
||||||
|
- [ ] Docusaurus loads data at build time.
|
||||||
|
- [ ] React components consume typed hooks rather than parsing source files.
|
||||||
|
- [ ] MDX contains composition and explanatory content rather than duplicate records.
|
||||||
|
- [ ] Data checks, typecheck, production build, browser view, Actions, and deployed route are verified.
|
||||||
Reference in New Issue
Block a user