feat(field-guide): creature habitat/kind schema (FG-1) #93

Merged
manlycucumber merged 1 commit from feat/field-guide-schema into develop 2026-07-11 18:18:36 +00:00
manlycucumber commented 2026-07-11 18:17:31 +00:00 (Migrated from github.com)

FG-1 of v0.4.0 — the schema spine the Field Guide's indices browse. Part of #92. Architecture: docs/architecture/field-guide.md.

What's here

Two closed-enum frontmatter fields on creature topics:

  • habitat — multi-valued (a fox is [woodland, farmland]); the "by habitat" axis.
  • kind — single-valued; the "by kind" axis. bestiary covers symbolic creatures (the basilisk).

Enforced with a .superRefine on topicFrontmatterSchema: required on creatures, forbidden elsewhere. The enums are closed, so a typo fails at parse and no axis page can ever be minted empty. Because the plugin spreads the whole parsed meta, the fields flow into virtual:bosco/contentTopicMeta/Topic with zero plugin changes, and isPublished stays category-blind — taxonomy never touches the doctrine gate.

Blast radius, threaded end to end. The standalone content pipeline (scripts/content/) carries a deliberate mirror of the frontmatter, so the two lists move together:

  • spec-schema.mjs — the mirror gains the same HABITATS/KINDS + .superRefine (byte-identical lists; emit.test.ts re-parses the tool's output through the real schema, which catches any drift).
  • emit.mjsbuildFrontmatter copies habitat/kind into the emitted index.md.
  • new-spec.mjs — scaffolds valid habitat/kind defaults for a creature stub.
  • Fixture + worked-example specs updated.

Backfilled creatures/red-fox and the gated creatures/basilisk-draft (which is schema-validated before the review gate excludes it, so it must parse — it exercises the bestiary kind).

Scope fence

No anatomy/range sub-schemas here (they land with their artifacts in FG-6/FG-7). No rendered-surface change — the hub, axis routes, and views land in FG-3a/FG-3b.

Verification (local gauntlet, all green)

check (0 errors) · lint · guard:colour · build (2 search records; basilisk gated out) · guard:external · guard:content · guard:provenance (3 topics, doctrine invariant holds) · guard:offline · 150 unit tests (+7). A focused adversarial pass confirmed the blast radius is fully covered (enum lists identical, gate-ordering handled, superRefine fail-closed, emit round-trip clean). e2e not run — no rendered surface changed.

**FG-1 of v0.4.0** — the schema spine the Field Guide's indices browse. Part of #92. Architecture: [`docs/architecture/field-guide.md`](docs/architecture/field-guide.md). ## What's here Two closed-enum frontmatter fields on **creature** topics: - `habitat` — multi-valued (a fox is `[woodland, farmland]`); the "by habitat" axis. - `kind` — single-valued; the "by kind" axis. `bestiary` covers symbolic creatures (the basilisk). Enforced with a **`.superRefine`** on `topicFrontmatterSchema`: **required on `creatures`, forbidden elsewhere**. The enums are **closed**, so a typo fails at parse and no axis page can ever be minted empty. Because the plugin spreads the whole parsed `meta`, the fields flow into `virtual:bosco/content` → `TopicMeta`/`Topic` with **zero plugin changes**, and `isPublished` stays category-blind — taxonomy never touches the doctrine gate. **Blast radius, threaded end to end.** The standalone content pipeline (`scripts/content/`) carries a deliberate mirror of the frontmatter, so the two lists move together: - `spec-schema.mjs` — the mirror gains the same `HABITATS`/`KINDS` + `.superRefine` (byte-identical lists; `emit.test.ts` re-parses the tool's output through the **real** schema, which catches any drift). - `emit.mjs` — `buildFrontmatter` copies `habitat`/`kind` into the emitted `index.md`. - `new-spec.mjs` — scaffolds valid `habitat`/`kind` defaults for a creature stub. - Fixture + worked-example specs updated. Backfilled `creatures/red-fox` and the gated `creatures/basilisk-draft` (which is schema-validated *before* the review gate excludes it, so it must parse — it exercises the `bestiary` kind). ## Scope fence No `anatomy`/`range` sub-schemas here (they land with their artifacts in FG-6/FG-7). **No rendered-surface change** — the hub, axis routes, and views land in FG-3a/FG-3b. ## Verification (local gauntlet, all green) `check` (0 errors) · `lint` · `guard:colour` · `build` (2 search records; basilisk gated out) · `guard:external` · `guard:content` · `guard:provenance` (3 topics, doctrine invariant holds) · `guard:offline` · **150 unit tests (+7)**. A focused adversarial pass confirmed the blast radius is fully covered (enum lists identical, gate-ordering handled, superRefine fail-closed, emit round-trip clean). e2e not run — no rendered surface changed.
Sign in to join this conversation.
No reviewers
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Bosco/bosco!93
No description provided.