Formalize the Knowledge Base on-disk format and tighten the entry schema per MASTER_SPEC §15.3-§15.10, §18.2. - compiler/common/categories.py: single source of truth for the 19 canonical categories (lowercase identifiers of the §18.2 list) plus is_valid_category. - knowledge_base_entry.schema.json (v1.1): category restricted to the 19; tags require at least one item; expand entries must be snake_case canonical ids; aliases uniqueItems. - knowledge_base/README.md: by-domain file layout, the "each file is a JSON array of entries" format, and contributor field rules (id/alias global uniqueness, tag order, expansion targets, one-tag minimum). - examples/knowledge_base.example.json: worked file demonstrating an alias and an expansion. Cross-entry rules (global uniqueness, expand targets exist) are deferred to the KB validation tooling (#9); this issue defines per-entry structure only. Tests: 19-category constant and schema-enum consistency, entry validation (category/tags/id/expand/unknown-field), and the worked example (array shape, per-entry validity, alias+expansion present, expand targets resolve). Co-authored-by: kunail0804 <kunail0804@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
45 lines
1.3 KiB
Python
45 lines
1.3 KiB
Python
"""The 19 canonical compiler categories (MASTER_SPEC §18.2, Appendix C.1).
|
|
|
|
Categories are defined by the compiler, not by the Knowledge Base (§15.5). This
|
|
module is their single source of truth: the Knowledge Base entry schema, the
|
|
Knowledge Base validation tooling, and the Category Splitter all draw the valid
|
|
category set from here so they cannot drift apart.
|
|
|
|
The §18.2 list is authoritative and uses Title-Case display names; we use the
|
|
lowercase identifier form here for machine use (Category Map keys and
|
|
``ResolvedTag.category``). The two forms correspond one-to-one, in order.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
# Ordered lowercase identifiers for the 19 categories of §18.2. Order is the
|
|
# authoritative spec order and is significant (e.g. category ordering downstream).
|
|
CANONICAL_CATEGORIES: tuple[str, ...] = (
|
|
"character",
|
|
"appearance",
|
|
"hair",
|
|
"face",
|
|
"eyes",
|
|
"expression",
|
|
"body",
|
|
"clothing",
|
|
"accessories",
|
|
"pose",
|
|
"action",
|
|
"interaction",
|
|
"objects",
|
|
"environment",
|
|
"camera",
|
|
"lighting",
|
|
"style",
|
|
"quality",
|
|
"miscellaneous",
|
|
)
|
|
|
|
_CATEGORY_SET = frozenset(CANONICAL_CATEGORIES)
|
|
|
|
|
|
def is_valid_category(category: str) -> bool:
|
|
"""Return True when ``category`` is one of the 19 canonical categories."""
|
|
return category in _CATEGORY_SET
|