diff --git a/SKILL.md b/SKILL.md
index 5676b37..ecac312 100644
--- a/SKILL.md
+++ b/SKILL.md
@@ -8,13 +8,14 @@ description: >
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
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
writing, because the answer decides the structure.
license: MIT
metadata:
author: workspace-skills-code-agent
- version: "1.1"
+ version: "1.2"
spec: agentskills.io/specification
framework: Diátaxis
hermes:
@@ -129,6 +130,10 @@ Use these replacements. This isn't optional:
## 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
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 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 |
+| 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 |
| Ship the site, or debug a failing build | [references/deployment.md](references/deployment.md) — Vercel, Netlify, GitHub Pages, Cloudflare, and common failures |
diff --git a/references/local-yaml-data-database.md b/references/local-yaml-data-database.md
new file mode 100644
index 0000000..6ec50c4
--- /dev/null
+++ b/references/local-yaml-data-database.md
@@ -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';
+
+
+
+
+```
+
+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.