From 26467ea1de5d30f1a75c684de637e968030e0f26 Mon Sep 17 00:00:00 2001 From: Jarvis Jr Hermes Date: Fri, 14 Aug 2026 09:58:31 +0000 Subject: [PATCH] feat: define local YAML documentation database --- SKILL.md | 10 +- references/local-yaml-data-database.md | 394 +++++++++++++++++++++++++ 2 files changed, 402 insertions(+), 2 deletions(-) create mode 100644 references/local-yaml-data-database.md 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.