Skip to content
Shapemetry

@huukhanhnguyen/types / model/conventions

model/conventions

Convention

Convention<D> = { checkFacts?: ConventionFinding[]; default: D; docId: string; lane: ConventionLane; snapshot?: ConventionSnapshot; tier: ConventionTier; }

Type Parameters

D

D = unknown

default

default: D

The out-of-box DEFAULT: pure data + pure functions (dependency-free, engine-safe) that make this lane's output standard-conforming with zero author input. This is where the magic numbers scattered through sheets.ts move to — owned, named, one place.

docId

docId: string

conventions/.md — the progressive-reference doc. gen assembles it into BOTH model-grammar.txt (AI) and the human docs. ONE source, so the AI guidance can never drift from what the DEFAULT actually does.

lane

lane: ConventionLane

snapshot?

optional snapshot?: ConventionSnapshot

The mandatory visual LOOK — required whenever the lane is visual.

tier

tier: ConventionTier

Methods

checkFacts()?

optional checkFacts(report): ConventionFinding[]

Deterministic self-check on an evaluated model's inspect report.

Parameters

report

InspectReport

Returns

ConventionFinding[]


ConventionFinding

ConventionFinding = { message: string; rule: string; severity: "error" | "warning"; }

One deterministic, in-engine finding — a MEASURABLE defect read off an evaluated inspect report ("title block has no Scale field", "content fills < 20% of the usable area"). Facts only; anything needing eyes is a snapshot.

message

message: string

rule

rule: string

Stable id for the rule, so a re-run can point at the same failed check (the reference's "re-run exactly the check that failed").

severity

severity: "error" | "warning"


ConventionLane

ConventionLane = string

A ModelJSON lane key a convention governs ("sheets", "views", "materials", "layers", …). A string, not ModelLane — that type names the fold ROLE (parameters/scene/component/flat), a different axis.


ConventionSnapshot

ConventionSnapshot = { judge: string; surface: "sheet" | "viewport3d" | "texture" | "material"; }

The mandatory LOOK, declared not executed. The engine is dependency-free and never opens a browser; it names the surface to render and the single yes/no question a vision-judge answers. The verify harness renders + judges.

judge

judge: string

ONE yes/no question about the rendered image, phrased so a "no" is a real defect ("Is the sheet a professional drawing — title block with labelled fields, framed content filling the page — not a tiny table in a corner?").

surface

surface: "sheet" | "viewport3d" | "texture" | "material"


ConventionTier

ConventionTier = "T1" | "T2"

Ontology tier (IFC/bSDD/USD applied-schema precedent). T0 core is engine-hard and never appears here. T1 STANDARD ships with the product, versioned. T2 DOMAIN is an opt-in pack (arch Psets, CNC tags). T3 MODEL is the author's own and is never a convention. Everything in this package is T1; a pack registers T2 via mergeConventions.


DrawingStandard

DrawingStandard = { frame: { bindingMargin: number; margin: number; zoneCols: number; zoneRows: number; zones: boolean; }; lineWeights: { border: number; center: number; dimension: number; hidden: number; titleBlock: number; visible: number; }; minContentFill: number; textSizes: { dimension: number; field: number; title: number; viewLabel: number; }; titleBlock: { fields: TitleBlockField[]; height: number; width: number; }; }

frame

frame: { bindingMargin: number; margin: number; zoneCols: number; zoneRows: number; zones: boolean; }

Frame + optional zone grid (ISO 5457). Binding edge (left) is wider.

bindingMargin

bindingMargin: number

margin

margin: number

zoneCols

zoneCols: number

zoneRows

zoneRows: number

zones

zones: boolean

lineWeights

lineWeights: { border: number; center: number; dimension: number; hidden: number; titleBlock: number; visible: number; }

Line weights in mm (ISO 128).

border

border: number

center

center: number

dimension

dimension: number

hidden

hidden: number

titleBlock

titleBlock: number

visible

visible: number

minContentFill

minContentFill: number

The composed content (views + tables) should occupy at LEAST this fraction of the usable area — the check that catches "a tiny table in a corner of a blank A3". Enforced by the snapshot judge +, once composition consumes this data, a facts check.

textSizes

textSizes: { dimension: number; field: number; title: number; viewLabel: number; }

Text heights in mm (ISO 3098).

dimension

dimension: number

field

field: number

title

title: number

viewLabel

viewLabel: number

titleBlock

titleBlock: { fields: TitleBlockField[]; height: number; width: number; }

Title block, bottom-right. ISO 7200 is ~180mm wide — an order of magnitude more than the current 60mm, with real labelled fields.

fields

fields: TitleBlockField[]

height

height: number

width

width: number


LightingStandard

LightingStandard = { ambient: number; hemisphere: number; hemisphereGround: number; key: number; surfaceColor: number; }

ambient

ambient: number

Ambient floor — shadow lift, never a second wash of fill.

hemisphere

hemisphere: number

Hemisphere fill (sky→ground), the directionless base.

hemisphereGround

hemisphereGround: number

Hemisphere ground colour (0xRRGGBB) — a cool grey so down-faces aren't black.

key

key: number

CameraData-parented key (directional). The dominant SHADING term; kept modest because a top-down view aims it at up-facing faces (N·L → 1).

surfaceColor

surfaceColor: number

The no-material surface colour (0xRRGGBB). A neutral CAD grey, never pure white — white × any real irradiance clips before edges describe the form.


MaterialStandard

MaterialStandard = { metalness: number; opacity: number; roughness: number; }

metalness

metalness: number

0 = dielectric (wood/plastic/paint), 1 = metal. Default dielectric: a metal with no IBL/environment reads as a dark mirror, the classic "why is my material black" surprise.

opacity

opacity: number

Fully opaque unless the material asks otherwise.

roughness

roughness: number

0 = mirror-smooth, 1 = fully diffuse. Default high: an unset material is a matte surface, not a gloss that blows a highlight.


TitleBlockField

TitleBlockField = { key: string; label: string; source: "title" | "number" | "scale" | "date" | "author" | "checker" | "revision" | "sheetOf" | "size" | "units" | "owner"; width: number; }

One title-block cell. width is a fraction of the block width; source says where the value comes from so the composer + the AI grammar agree on it.

key

key: string

label

label: string

source

source: "title" | "number" | "scale" | "date" | "author" | "checker" | "revision" | "sheetOf" | "size" | "units" | "owner"

How the value is filled: a sheet/model field, or author-entered.

width

width: number

Fraction of the title-block width this field's cell spans (rows pack to 1).

Last updated: 📖 6 min readEdit on GitHub