docs(bgm): derive definition names from role.type

This commit is contained in:
2026-08-10 16:27:45 +08:00
parent aab0b66ee8
commit 23332ab786
+46 -30
View File
@@ -84,50 +84,51 @@ declaration, then uses its `include` paths to find the definitions.
### Code blocks as virtual files
A code block is a virtual definition file. To give it a name — so `include:`
and `$variants` paths can resolve against it — add a `file=` segment to the
code block's info string. The name is relative to the current markdown file:
A code block is a virtual definition file. Its name is derived from the
`role=` on its info string — `role.type.lang` — so it is discoverable by the
default `include: ./**/*.yaml` and addressable by that name:
````md
```yaml file=parts/cargo.yaml
```yaml role=part.cargo
...
```
```csv file=parts/cargo.csv
```yaml role=surface.game#main
...
```
```yaml role=package
...
```
````
- A block with `file=` is addressable by that path.
- A block without `file=` is auto-named `./${hash}.yaml`, where `hash`
is derived from its content. This makes every yaml block naturally
discoverable by the default `include: ./**/*.yaml`. Identical blocks dedupe
to the same hash.
- The `file=` name is what `$variants: ./cargo.csv` and `include: parts/*.yaml`
resolve against. When there is a real file in that path, the codeblock wins.
- `file=` implies the file type from its extension; the language tag is
optional and only for editor highlighting.
- **Hash vs explicit `file=`:** a hashed name is for auto-discovery, not for
referencing. To point at a specific yaml block by name, give it an explicit
`file=`; otherwise its name is content-derived and unstable.
- `role=part.cargo` names the block `part.cargo.yaml`.
- `role=surface.game#main` names it `surface.game.yaml`.
- `role=package` names it `package.yaml`.
- The name is what `$variants: ./cargo.csv` and `include: parts/*.yaml`
resolve against. When there is a real file in that path, the codeblock wins.
- `file=` overrides the auto-name when present, e.g. `file=parts/cargo.yaml`
names the block `parts/cargo.yaml` regardless of its role.
- A block without `role=` is **not** a definition — it is ignored. Discovery
is explicit: a block is a definition only when its `role=` (or, for real
files, its filename) declares a known `role.type`.
### role= on the info string
A block's `role` can be declared on the info string instead of in the content,
using the same `role.type#id` shape as the block's identity. `type` and `id`
are optional — anything not given comes from the content (or from `$variants`
rows):
A block's role is declared on the info string, using the same `role.type#id`
shape as the block's identity. `type` and `id` are optional — anything not
given comes from the content (or from `$variants` rows):
````md
```yaml file=parts/cargo.yaml role=part.cargo
```yaml role=part.cargo
...
```
```yaml file=board.yaml role=surface.game#main
```yaml role=surface.game#main
...
```
```yaml file=game.yaml role=package
```yaml role=package
...
```
````
@@ -139,8 +140,21 @@ rows):
- A `role`/`type`/`id` given on the info string **conflicts** with the same
key in the content and errors. `id` on the info string cannot combine with
`$variants`, since every row supplies its own `id`.
- Without `role=`, discovery works exactly as before: the role comes from the
content's `role:` field.
- A block without `role=` is not a definition — discovery is explicit (see
above).
### Real files
A real `role.type.lang` file (e.g. `part.cargo.yaml`) is a definition by its
filename, with no `role=` needed. `role` and `type` are parsed from the name;
`id` comes from the content or `$variants`. A real file and a code block with
the same name are the same definition; the code block wins.
### Duplicates
Two definitions with the same `role.type` are grouped under the same name.
They must not define the same `id` — a duplicate `type#id` errors. Blocks with
the same `role.type` but different ids are fine.
### include
@@ -160,7 +174,8 @@ package can use a `../`-relative pattern or an absolute-from-root pattern
## 3. Roles
json objects in yaml blocks are handled if they have a `role:` field for either
json objects in yaml blocks are handled if they are declared as a definition
by their `role=` (or, for real files, their filename) for either
- `package`
- `part`
- `surface`
@@ -171,9 +186,10 @@ a valid object can either be the root or in the list of the yaml block.
for all roles except package, `type` and `id` are needed.
`type#id` is used for identification so that combo must be unique in the package.
A block may declare its role on the info string instead — `role=part.cargo` is
equivalent to `role: part` + `type: cargo` in the content (see §2). The info
string and content must not both set the same key.
A block declares its role on the info string — `role=part.cargo` is equivalent
to `role: part` + `type: cargo` in the content (see §2). A real file declares
it in its filename. The info string/filename and content must not both set the
same key.
### package