Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/contracts.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,13 @@ bytes nor keys; the file names of `original` and `cas` both follow from the reco
`original` manifest alone. Documents derived for `original` from records and paths (the views with the files of
their objects) are the exception: `original` has the derived documents, `cas` the artifacts they are made from.

## Product manifest: nnnotes.product/1

A product layout writes, for each product of `pipeline.assemble`, a manifest
([product.schema.json](https://github.com/MetaSekaiLab/nnnotes/blob/main/src/nnnotes/schemas/product.schema.json)): the product's
files and the files of the objects it uses, each a content-addressed `assets/<sha256>.<ext>`. The product's object
table is `nnnotes.objects/1`. See [products](products.md).

## Reports

- Coverage, `nnnotes.coverage/1` ([coverage.schema.json](https://github.com/MetaSekaiLab/nnnotes/blob/main/src/nnnotes/schemas/coverage.schema.json)): per class the census
Expand All @@ -224,6 +231,7 @@ Documents written by particular stages (artifacts of no object: their ids are `<
| `nnnotes.scripts/1` | `link.scripts` | [scripts.schema.json](https://github.com/MetaSekaiLab/nnnotes/blob/main/src/nnnotes/schemas/scripts.schema.json) |
| `nnnotes.addresses/1` | `link.addresses` | [addresses.schema.json](https://github.com/MetaSekaiLab/nnnotes/blob/main/src/nnnotes/schemas/addresses.schema.json) |
| `nnnotes.view/1` | `view.<name>` | [view.schema.json](https://github.com/MetaSekaiLab/nnnotes/blob/main/src/nnnotes/schemas/view.schema.json) |
| `nnnotes.objects/1` | `pipeline.assemble` (a product's object table) | [objects.schema.json](https://github.com/MetaSekaiLab/nnnotes/blob/main/src/nnnotes/schemas/objects.schema.json) |

The catalog versions of a depot, `nnnotes.catalogs/1` ([catalogs.schema.json](https://github.com/MetaSekaiLab/nnnotes/blob/main/src/nnnotes/schemas/catalogs.schema.json),
`<depot>/catalogs/index.json`), and the difference between two of them, `nnnotes.catalog-diff/1`
Expand Down
83 changes: 83 additions & 0 deletions docs/products.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Products

A product is something a player or a site reads as a whole: a Live2D model, a story episode, a live. Products are
assembled from the results of `unity.export` ([stages](stages.md)), never from a bundle: by the time a product is
made, every object it uses has been converted once, and the product combines those conversions with what it adds
itself.

## Product stages

A product stage (`nnnotes.pipeline.assemble.ProductStage`) has one task per subject. Its task starts from root
objects:

- the objects of the catalog keys the stage gives for the subject (`keys`), through the address table of
`link.addresses`;
- the object ids the stage names besides (`root_objects`).

Both are read from the planning facts alone, so a command can ask for what its products need before anything runs:
`assemble.request(stages, products, env)` gives the fact `roots` (`{"keys", "objects"}`), and the request of
`unity.export` then holds the units of those objects and every unit reachable from them through the census `refs`
([units](stages.md#units)), and nothing else of their bundles.

What a task reaches: the units holding its roots, then every unit that an item of a reached unit references (the
item's `refs`), through the `unity.export` results. A sprite whose atlas is in another bundle has its `image` from the
`sprite.crop` result of that atlas. A reached unit that the request did not export is an error of the request; an
object that a reached object references and no census holds is listed as `missing`.

| Part of the task | |
|---|---|
| inputs | `objects`: the object table of what it reaches (`nnnotes.objects/1`); the stage's own inputs (master tables, data its parameters name) |
| depends | `link.addresses` (when it has keys), the `unity.export` and `sprite.crop` tasks whose results it read |
| artifacts | `<task id>#<path>`: the product's own files; `<task id>#objects`: the object table of the objects its files use (the whole table unless the stage narrows it) |
| item | one for the subject: `exported`, or `unsupported` with a reason code |

The key holds the object table, so a product is assembled again exactly when a file of an object it reaches
changes, or what it reaches changes.

## Object table: nnnotes.objects/1

([objects.schema.json](https://github.com/MetaSekaiLab/nnnotes/blob/main/src/nnnotes/schemas/objects.schema.json))

```json
{"schema": "nnnotes.objects/1",
"roots": ["CAB-…:-4153…"],
"objects": {
"CAB-…:-4153…": {"status": "exported", "class": "GameObject", "name": "model",
"files": {"json": {"sha256": "…", "size": 5120, "ext": "json"}}},
"CAB-…:12": {"status": "contained", "class": "Transform", "in": "CAB-…:-4153…"},
"CAB-…:40": {"status": "exported", "class": "Texture2D", "name": "texture_00",
"files": {"image": {"sha256": "…", "size": 812345, "ext": "png"},
"json": {"sha256": "…", "size": 640, "ext": "json"}}}},
"missing": []}
```

Each object has the status of its item (the most severe when two stages made items for it), its class and name
where known, its files by role (the artifacts of its items), the object whose file holds it (`in`, a contained
object), or the reason code of a generic, unsupported or failed object.

## Product layout

A product layout places products for a player:

- every file of a product and every file of the objects of its object table at `assets/<sha256>.<ext>` (a file
several products or objects share is written once);
- each product's manifest at `<directory>/<file>.json` (the stage's `manifest(subject)`, by default
`<stage>/<subject>.json` with the subject escaped as one path segment).

## Product manifest: nnnotes.product/1

([product.schema.json](https://github.com/MetaSekaiLab/nnnotes/blob/main/src/nnnotes/schemas/product.schema.json))

```json
{"schema": "nnnotes.product/1", "product": "live2d.model", "subject": "…",
"files": {"model.json": {"asset": "assets/<sha256>.json", "size": 2048}},
"objects": {
"CAB-…:-4153…": {"class": "GameObject", "name": "model",
"files": {"json": {"asset": "assets/<sha256>.json", "size": 5120}}},
"CAB-…:12": {"class": "Transform", "in": "CAB-…:-4153…"}}}
```

`files` are the product's own files by path; `objects` are the objects of its object table that have files, or are
contained in an object that has one. An asset path is relative to the directory above the manifest's directory, as
in the chart manifests of ournotes-player. A reference in an object's JSON (`{"$ref": {"file", "pathId"}}`) names
the object `<file>:<pathId>` of `objects`.
2 changes: 2 additions & 0 deletions docs/schemas.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ schemas.load("plan") # the schema as a dict
| `failures` | `nnnotes.failures/1` | the failed tasks and items of a run |
| `layout` | `nnnotes.layout/1` | the files a layout owns in its output directory |
| `music-data` | `nnnotes.music-data/2` | every song and chart of one master data version ([music data](music-data.md)) |
| `objects` | `nnnotes.objects/1` | the objects a product reaches: their class, item status and files ([products](products.md)) |
| `plan` | `nnnotes.plan/1` | what a run would do and why (`depot plan`) |
| `product` | `nnnotes.product/1` | a product's manifest: its files and the files of the objects it uses, as content-addressed assets ([products](products.md)) |
| `result` | `nnnotes.result/1` | the result of a task, a function of its key alone |
| `run` | `nnnotes.run/1` | a run manifest: context, selection, tasks with keys and statuses, layouts |
| `scripts` | `nnnotes.scripts/1` | every MonoScript of the censuses, by object id |
Expand Down
8 changes: 4 additions & 4 deletions docs/stages.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,10 @@ hierarchy. Its subject is the stable address of its root object, `<stable bundle
several serialized files the file's tag follows the bundle name, as in `link.addresses`): path ids stay when a
bundle's content changes, so a unit keeps its task across catalog versions.

A run exports the units holding an object of the selected bundles and every unit reachable from those through what
their objects reference (the census `refs`, across the censuses of the run); with `--only-class` only the units whose
root object is of those classes. The selection is not part of any key: a unit's task is the same whichever request
reaches it.
A run exports the units holding an object of the selected bundles, the units of the objects the fact "roots" names
(a product's roots: [products](products.md)) and every unit reachable from those through what their objects reference
(the census `refs`, across the censuses of the run); with `--only-class` only the units whose root object is of those
classes. The selection is not part of any key: a unit's task is the same whichever request reaches it.

A task's key includes the atoms `reader` and `sniff`, the converter `generic.json`, the converters (with their
atoms) of the classes of the unit's objects, its bundle, its root and the script entries and shipped type trees its
Expand Down
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ nav:
- Python API: api.md
- Contracts: contracts.md
- Stages: stages.md
- Products: products.md
- Views: views.md
- Replay data: replay.md
- UI library: ui.md
Expand Down
Loading
Loading