| id | 156 | ||
|---|---|---|---|
| title | Composable required-structure schemas across multiple kinds | ||
| status | ✅ | ||
| summary | Two kinds whose required-structure schemas differ overwrite each other under deep-merge. This plan adds composition so a directive-rule-readme kind layers on top of rule-readme without losing either constraint set. | ||
| model | opus | ||
| depends-on |
|
A file resolved by N kinds gets one effective required-structure schema. That schema must be the composition of each kind. Today the last-written schema wins.
The driving use case is the new directive-rule-readme kind from PR #274. It must layer a required Pattern section onto rule-readme. The same shape applies later to runbook + on-call or plan + epic pairs.
The config merge layer in internal/config/
already deep-merges rule settings across layers
(defaults, kinds, overrides). Scalar replacement
plus map-key merging covers most rules. See
merge.go for the
implementation.
required-structure is the outlier. Its setting is
either schema: (a path to a proto.md file) or
inline-schema: (a parsed Schema). Two kinds that
both set schema: deep-merge as scalars and the
second wins. One kind sets schema: and another
sets inline-schema:: MDS020 today picks one and
drops the other. Neither path composes.
-
✅ Baseline note landed in the cross-system doc. It describes the new composition rule. The note doubles as the public contract.
-
✅ Chose composition rule option 1.
- Sections concatenate.
- Same-heading scopes merge.
- Frontmatter conjoins via CUE
&. - Stricter
closed:wins. Require.Filenamepicks the first non-empty pattern.- Conflicting patterns error.
- Acceptance test: compose_test.go.
-
✅ Merge layer accumulates a
schema-sourceslist across layers. Each layer that setsschema:orinline-schema:contributes one entry. The rule loads the list and callsschema.Composeat check time.Tests in schema_kinds_test.go cover disjoint sections, disjoint frontmatter, and the kind-plus-override path. compose_test.go exercises the end-to-end Check path.
-
✅ The four directive READMEs now resolve to both
rule-readmeanddirective-rule-readmein .mdsmith.yml. The directive-proto.md schema lost the duplicated headings. It now declares only thePatternsection. Thenaturefrontmatter narrows to"directive". Each directive README movedPatternto the end so the composed section order matches:rule-readmefirst, thendirective-rule-readme. -
✅ Composition rule lives in schemas.md with the worked
rule-readme + directive-rule-readmeexample. The MDS020 README points at the guide.
- A file resolving to two kinds with disjoint
required sections fails
mdsmith checkuntil both sets are present. - A file resolving to two kinds with disjoint
required front-matter keys fails
mdsmith checkuntil both sets are present. -
internal/rules/directive-proto.mdno longer duplicates rule-readme'sConfig,Examples, andMeta-Informationheadings; it declares only Pattern additions. - docs/guides/schemas.md documents the composition rule with a two-kind worked example.
- All tests pass:
go test ./.... -
go tool golangci-lint runreports no issues.