Initialize an aerospace concept
Interpret the invocation as:
/initialize-aero <concept> "<intent>" @requirement-docs @sketch-images @reference-model
Create the reviewable source bundle in designs/<concept>/; do not run the
full pipeline, invoke MDO, create a commit, or modify the source documents.
In particular, never invoke python -m openair run; the only solver stages
authorized here are python -m openair.reference ingest and
python -m openair.geometry run.
1. Resolve and guard
- Work from the repository root.
- Require a concept name and non-empty intent. Accept
<name> or
designs/<name>.
- Apply the exact rules in
openair.designer.server.concept_name: reject
absolute paths, .., nested paths, reserved _ names, and characters
outside letters, numbers, ., _, and -.
- Refuse if
designs/<name> already exists. Point the user to
python -m openair.designer <name> --open or ask for a new name. Never
merge into or replace an existing concept.
- Refuse if
results/<name>/ already exists: stale artifacts can be mistaken
for this draft's checkpoint. Ask the user to remove/rename them or choose a
new concept; this skill never deletes results.
- Treat
designs/_template/design.yaml as the schema-complete starting
contract. Do not edit the template.
2. Ingest and classify sources
- Read every attached text/Markdown source. Extract requirements, preferences,
propulsion facts, units, configuration intent, and explicit uncertainties.
Distinguish quoted facts from engineering assumptions.
- View every image directly; do not classify it from the filename. Classify
each usable aircraft image as top, side, or front. Record ambiguous views.
- Choose at most one primary image per view for the source bundle. Keep every
attachment in the
brief.md source list even if it is not the primary
trace. If a primary image cannot be classified confidently, ask the user;
do not guess its canonical filename.
- Establish image scale and distortion:
- Prefer a stated dimension or visible dimension line.
- Otherwise use the sketch grid after accounting for perspective.
- If neither supplies absolute scale, preserve normalized shape ratios and
infer an absolute fuselage length from propulsion/payload packaging.
- If an oblique photo cannot be reliably rectified, widen its tolerance and
say so. Never present pixel precision as physical accuracy.
Copy or convert the primary views to exactly:
designs/<name>/sketch-top.png
designs/<name>/sketch-side.png
designs/<name>/sketch-front.png
Only create files for supplied views. Apply EXIF orientation before PNG
conversion, record the conversion in the brief, and verify each output starts
with the PNG signature 89 50 4E 47 0D 0A 1A 0A. These names are the Design
Studio save whitelist and report contract.
2b. Ingest a reference model (when one is attached)
A reference model is a triangle mesh of the real aircraft (3D scan or CAD
export). Read docs/guidebook/13-reference-models.md; it is the contract and
is tool-agnostic on purpose.
Accept only triangle meshes (STL, PLY, OBJ, 3MF, GLB/glTF, OFF). If the
attachment is a native CAD, scan-project, or point-cloud file, stop and ask
the user to export a triangle mesh from their tool with an explicit length
unit, optionally with a <stem>.reference.json sidecar. Give no
vendor-specific instructions; the repository does not know or care which
tool produced the mesh.
Establish the unit (--units or sidecar units), the source frame
(--axes, open-air axis <- signed source axis), and one anchor dimension
(--expect-span-m, or the sidecar's measured_span_mm). Never guess a
unit: the anchor cross-check exists to abort on a wrong one.
Dry-run first, from the repository root with the environment of section 5:
python -m openair.reference ingest <mesh> --concept <name> --units mm \
--axes "<mapping>" --expect-span-m <anchor> \
--treatment <reproduction|inspiration|requirement> \
--out <staging>/reference --dry-run
View reference-sections-dryrun.png. Confirm the body edge excludes the
wing, LE/TE stations follow the fitted lines, station envelopes match their
fitted super-ellipses, airfoil sections have the expected thickness and
camber sign, and fins sit on the deck. Fix --axes/--datum and repeat
until the figure is right; then run without --dry-run, with
--sketch-dir <staging> so the silhouettes land beside design.yaml.
Treat everything under reference.json .suggested as measured
(reference model) with the tolerances in .tolerances: planform (span,
root chord by centreline extrapolation, measured wing.sections, and their
area/MAC-locus-equivalent sweep/taper/dihedral descriptors), body stations
with section powers,
fin geometry, t_over_c plus the NACA four-digit fit, and, when resolved,
the hinge line and as-scanned control deflection. Read the notes, the
per-station fill_method/width_clamped/top_overridden flags, and the
width_core_m versus width_blended_m choice; decide deliberately and
write the reason in the brief.
4a. For a reproduction with measured wing stations, copy the complete
suggested.wing.sections list and its scalar equivalents together; never
hand-pick one without re-deriving the other. Inspect
disclosures.wing_planform and the solid section outline in
reference-sections.png: confirm the body-exclusion width, mandatory
root/straight-band/tip breakpoints, gross area, and simplification
tolerance. Section-local t/c is an inferred absolute-thickness loft
control, not another airfoil cut; keep the measured global
wing.t_over_c for OAS/wingbox physics.
For inspiration or requirement intent, pass that treatment to ingest;
sections remain disclosed as a reproduction alternative but
suggested.wing stays scalar and valid for MDO.
4aa. When measurements.fairings.aft_shoulder.ok, inspect its fin-point
exclusion, fit RMS/acceptance, dimensional and contour simplification
residuals, skin penetration, nominal/effective hidden skirt, support
adjustment, total burial, and junction crease in
reference-sections.png. For a reproduction copy the
complete suggested.fuselage.fairings list; do not hand-tune its stations.
max_width_loc: -1 is the measured dome convention. Inspiration and
requirement modes keep the candidate disclosed but do not emit it.
4b. When the fin measurement resolves a root junction, write its mirrored
absolute y and shared z into vtail.y_root_m/z_root_m and set
vtail.root_attachment: measured. The default derived mode intentionally
ignores those coordinates and applies the legacy 60%-body rule; never use
it for a measured reference-model reproduction. If the measured junction
needs a shoulder fairing, require the generated fairing plus derived buried
root extension; never project the exposed fin inward or relax attachment QA.
The scan silhouettes (sketch-top/side/front.png) are the primary views:
orthographic, rectified by construction, 10 mm grid, mm/px in the PNG
metadata. Keep any photographs or renders in the source list as secondary
evidence only; never let a render overrule the scan.
What a reference model cannot supply stays placeholder or comes from the
measurement documents: mass, CG, inertia, control travel and trimmed
neutral, thrust, materials, solver constants. The as-scanned control
deflection is a control position at scan time, not a trim.
6b. When the scan resolves a hinge line, write the control surface into
flight_dynamics.control_surfaces (hinge → chord_fraction, first/last
detection → span fractions, provenance measured (reference model)), put
the measured travel in max_up_deg/max_down_deg, the flown neutral in
neutral_deg (or null when nobody measured it), and the as-scanned
position as the starting trim_deflection_deg. For a tailless airframe
whose twist is a measurement, set mission.pitch_trim_control: elevon so
the pipeline trims with the elevon instead of re-twisting the wing
(guidebook chapters 03, 09). Trailing edge up is positive everywhere.
A reference-model reproduction defaults to sketch.treatment: reproduction with hard_scale: 1.0; use inspiration only when the
intent asks for a redesign grounded on the scan.
Record in the brief: source file, sha256, declared unit, anchor check,
axes mapping, symmetry residual, pitch rotation applied to reach the
root-chord datum, shells dropped, and every scan weakness the ingest
flagged (open noses, incomplete leading edges, repaired hatches, mirrored
halves). The reference is measured design input; it is never validation
truth.
3. Measure before authoring
Use a common coordinate convention: x/L=0 at the nose, x/L=1 at the tail,
positive y from centerline to wingtip, and a documented vertical datum for
z. Measure the silhouette, not shading or perspective margins.
Record source, image-space endpoints/contour coordinates, method, scale,
value, tolerance, and provenance (measured, measured (reference model),
inferred, or defaulted) for every item below. Pixel coordinates are
evidence, not false precision: label agent-read coordinates approximate and
preserve wider physical tolerances. When a reference model was ingested, its
measurement record replaces pixel reading for every quantity it covers; use
pixel measurements only for what the mesh does not show.
Planform
- Fuselage length and full maximum width.
- Wing span, root chord, tip chord, taper, and wing-root leading-edge
x/L.
- Leading-edge sweep with the schema sign convention:
atan((x_tip_LE - x_root_LE)/(span/2)); forward sweep is negative.
- Tail span, root chord, sweep, cant, and longitudinal placement where visible.
These measurements must become optional
sketch.fin_* priors, not only
prose in the worksheet.
Compute and cross-check:
span_over_length = wing.span_m / fuselage.length_m
root_over_length = wing.root_chord_m / fuselage.length_m
taper = tip_chord_m / root_chord_m
x_le_root_over_length = wing.x_le_root_m / fuselage.length_m
Fuselage loft
Use 6–8 shared x/L stations covering nose, forebody, maximum section,
wing/inlet transitions, aft deck, boattail, and tail tip.
- From top view, measure the full body width at each station.
- From side view, measure upper and lower contours at the same stations.
Set
height_m = z_top - z_bottom and
z_offset_m = (z_top + z_bottom)/2 relative to the stated datum.
- Keep stations strictly increasing, with endpoints at 0 and 1. Interior
stations must have positive width and height.
- Set
max_width_m and max_height_m to the station maxima.
- If a front/cross-section view is absent, label section curvature inferred.
Read the historical parameter contract in
docs/history/2026-08-20-1942-super-ellipse-and-parameter-audit.md before
choosing section powers. Use its supported split-super-ellipse range and start
from:
ellipse: side 2.0, top 2.0, bottom 2.0
wide knife blade: side about 1.2, top about 2.0, bottom about 2.0
bubble over hull: side about 1.6, top about 1.6, bottom about 5.0
slab / box: side 4–8, top 4–8, bottom 4–8
Powers control section curvature, not top/side silhouette dimensions. Do not
invent unsupported canopy or inlet fields. A multi-section wing is permitted
only for a source-locked reproduction and only from measured/reference station
evidence; use the ingest-generated list rather than tracing arbitrary panels.
Record visible but still unrepresentable features as limitations in the brief.
Tolerance discipline
- Give every image measurement a nonzero tolerance based on grid resolution,
line thickness, rectification, and view ambiguity.
- Oblique/unrectified photos require wider bounds than orthographic drawings.
- Start conservatively; tighten
sketch: tolerances only after a Studio
re-trace supports it.
- Keep exact document values and unit conversions traceable to their source.
- Mark hidden-view dimensions, airfoil, twist, material gauges, solver
constants, propulsion lapse/TSFC coefficients, and mass guesses as inferred
or template-defaulted; sketches do not prove them.
4. Author the source bundle
Create a temporary sibling staging directory under designs/ only after the
guard and source review. Author the complete bundle there. Before publication,
validate the YAML, concept name, brief markers, canonical PNG names/signatures,
and allowed file set (design.yaml, brief.md, sketch-*.png, and the
optional reference/ directory with reference.json, reference.ply, and
reference-sections.png); also reject unchanged template placeholders such as
new-aero-concept or its starter notes. Publish with one same-filesystem
os.replace(staging_dir, designs/<name>) only while the target is still
absent. Remove the staging directory on any failure. Never expose a partially
written concept.
The complete staged bundle contains:
design.yaml
Start from designs/_template/design.yaml, keep every schema section, and:
Set name, concise notes, measured sketch: ratios, and their tolerances.
New sketch-authored concepts default to autonomous prior treatment:
sketch:
treatment: inspiration
hard_scale: 3.0
fidelity_weight: 1.0
One tolerance is the no-penalty visual envelope; hard_scale × tolerance
is the immutable identity bound. Populate every measured
fin_span_m/fin_span_tol_m,
fin_root_chord_m/fin_root_chord_tol_m,
fin_le_sweep_deg/fin_le_sweep_tol_deg,
fin_cant_deg/fin_cant_tol_deg, and
fin_x_le_m/fin_x_le_tol_m pair. Use requirement only when the user
explicitly says the measured geometry must not depart.
Set wing, fuselage station loft and powers, tails, and placement from the
measurement record.
Populate mission and published engine facts from the requirement sources,
converting to SI and showing conversions in the brief. For example,
45 kgf = 441.299 N and 1100 g/min = 0.0183333 kg/s.
Use template values elsewhere. Do not retune advanced solver calibration
from a sketch.
Keep payload and fuel locations physically inside the measured body and
preserve their provenance/bounds in sketch:.
Do not add computed Pydantic fields or generated specifications under
designs/.
brief.md
Write, in order:
- Intent and configuration summary.
- Source list, including view classification and output PNG mapping.
- Requirement record with units, source, tolerance, and status.
- Coordinate/scale/rectification method.
- Measurement and inference record with value, tolerance, provenance, and
rationale.
- Defaults retained from the template, grouped by dotted path with rationale.
- Visible unsupported features and expected fidelity limits.
- Geometry-checkpoint iteration log.
All durable source, measurement, and inference content must remain outside
these markers because a later Studio save replaces their contents:
<!-- OPENAIR_SKETCH_WORKSHEET_START -->
## Sketch measurement worksheet
Short generated-compatible summary of the current geometry.
<!-- OPENAIR_SKETCH_WORKSHEET_END -->
Inside the worksheet, record unsupplied rectification honestly, for example
not rectified (bootstrap — approximate agent image-space measurement).
Never fabricate four-point controls or grid scale. For scan silhouettes write
orthographic projection of the reference mesh, <mm/px> mm/px, 10 mm grid (rectified by construction) and cite reference.json.
5. Validate and run the bounded geometry loop
Read .cursor/skills/aero-qa-geometry/SKILL.md and
docs/guidebook/01-openvsp.md. Activate the environment before Python starts:
source .venv/bin/activate
export LD_LIBRARY_PATH="$PWD/tools/libs/usr/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH:-}"
export PATH="$PWD/tools/openvsp/opt/OpenVSP:${PATH:-}"
export PYTHONPATH="$PWD/src:${PYTHONPATH:-}"
export OPENMDAO_REPORTS=0
Before each geometry run, validate the YAML through VehicleSpec:
python -c 'import sys,yaml; from openair.schemas import VehicleSpec; VehicleSpec.model_validate(yaml.safe_load(open(sys.argv[1])))' "designs/<name>/design.yaml"
python -c 'import sys,yaml; from openair.schemas import VehicleSpec; from openair.reporting.report import _shape_fidelity; s=VehicleSpec.model_validate(yaml.safe_load(open(sys.argv[1]))); r=_shape_fidelity(s); assert r["ok"], r' "designs/<name>/design.yaml"
python -m openair.geometry run "designs/<name>"
Run at most three total geometry iterations. After each run:
- Inspect
results/<name>/baseline/geometry.json, not only top-level ok.
Require:
.openvsp.readback.matches_spec == true
.openvsp.stl_bbox.ok == true
.openvsp.mesh_checks.ok == true
.packing.ok == true
.openvsp.errors is empty
_shape_fidelity(spec)["ok"] == true
- when a reference model exists:
.reference_fidelity.available == true
and, for a reproduction, .reference_fidelity.ok == true (body p95
surface deviation and top/side silhouette IoU inside the acceptance
recorded in reference.json; wing/fin and whole-aircraft p95 are
disclosed under .reference_fidelity.disclosed).
- Open
results/<name>/baseline/threeview.png beside all source sketches.
Compare span/length, chord ratios, sweep sign/magnitude, wing station,
fuselage top/side silhouettes, deck/belly centerline, and fin placement
against the recorded tolerances. When a reference model exists, also open
results/<name>/baseline/reference_overlay.png and read
reference_fidelity.silhouettes (reference-only versus model-only area)
and .stations/.planform deltas: every departure must correspond to a
feature the brief already lists as unrepresentable (strakes, root blends,
rounded tips, open hatches), never to a measurement you could correct.
- Append the observed mismatch and source-level adjustment to the brief's
iteration log. Adjust
design.yaml, never result artifacts or
reference/.
- Repeat only when the source bundle changed. Stop when checks pass and the
visible shape is within tolerance, or after iteration three.
Packing is a real constraint, not permission to silently distort the sketch.
If the engine or payload cannot fit within measured tolerance, report the
conflict and the available upstream choices. If an artifact-truth check fails
for a tooling reason, report the blocker rather than weakening the check.
6. Report and hand off
Report:
- files created;
- a concise table separating measured, measured (reference model), inferred,
and defaulted values;
- remaining unsupported or low-confidence shape features, including every
scan weakness the ingest flagged;
- geometry JSON evidence and whether the three-view is within tolerance;
- the baseline
threeview.png inline, and reference_overlay.png with the
reference_fidelity numbers when a reference model exists;
- whether the three-iteration limit was reached.
State explicitly that initialization is a geometry checkpoint, not full
aircraft validation. In interactive mode, offer the live Studio for a visual
review and validated save. In explicitly autonomous/no-manual-review mode,
Studio review is optional: the measured bundle may proceed directly to
/create-aero after its source files are committed, and the inspiration-mode
MDO must correct suboptimal geometry while documenting departures. End with:
python -m openair.designer <name> --open
# Or skip Studio in autonomous mode. After committing the source bundle:
/create-aero designs/<name>
1---2name: initialize-aero3description: Bootstraps a complete open-air source concept from an intent, requirement documents, aircraft sketches, and optionally a reference 3D model (triangle mesh of the real aircraft), then checks the baseline mesh against the source shape. Use only when explicitly invoked as /initialize-aero.4---56# Initialize an aerospace concept78Interpret the invocation as:910```text11/initialize-aero <concept> "<intent>" @requirement-docs @sketch-images @reference-model12```1314Create the reviewable source bundle in `designs/<concept>/`; do not run the15full pipeline, invoke MDO, create a commit, or modify the source documents.16In particular, never invoke `python -m openair run`; the only solver stages17authorized here are `python -m openair.reference ingest` and18`python -m openair.geometry run`.1920## 1. Resolve and guard21221. Work from the repository root.232. Require a concept name and non-empty intent. Accept `<name>` or24 `designs/<name>`.253. Apply the exact rules in `openair.designer.server.concept_name`: reject26 absolute paths, `..`, nested paths, reserved `_` names, and characters27 outside letters, numbers, `.`, `_`, and `-`.284. Refuse if `designs/<name>` already exists. Point the user to29 `python -m openair.designer <name> --open` or ask for a new name. Never30 merge into or replace an existing concept.315. Refuse if `results/<name>/` already exists: stale artifacts can be mistaken32 for this draft's checkpoint. Ask the user to remove/rename them or choose a33 new concept; this skill never deletes results.346. Treat `designs/_template/design.yaml` as the schema-complete starting35 contract. Do not edit the template.3637## 2. Ingest and classify sources38391. Read every attached text/Markdown source. Extract requirements, preferences,40 propulsion facts, units, configuration intent, and explicit uncertainties.41 Distinguish quoted facts from engineering assumptions.422. View every image directly; do not classify it from the filename. Classify43 each usable aircraft image as top, side, or front. Record ambiguous views.443. Choose at most one primary image per view for the source bundle. Keep every45 attachment in the `brief.md` source list even if it is not the primary46 trace. If a primary image cannot be classified confidently, ask the user;47 do not guess its canonical filename.484. Establish image scale and distortion:49 - Prefer a stated dimension or visible dimension line.50 - Otherwise use the sketch grid after accounting for perspective.51 - If neither supplies absolute scale, preserve normalized shape ratios and52 infer an absolute fuselage length from propulsion/payload packaging.53 - If an oblique photo cannot be reliably rectified, widen its tolerance and54 say so. Never present pixel precision as physical accuracy.5556Copy or convert the primary views to exactly:5758```text59designs/<name>/sketch-top.png60designs/<name>/sketch-side.png61designs/<name>/sketch-front.png62```6364Only create files for supplied views. Apply EXIF orientation before PNG65conversion, record the conversion in the brief, and verify each output starts66with the PNG signature `89 50 4E 47 0D 0A 1A 0A`. These names are the Design67Studio save whitelist and report contract.6869## 2b. Ingest a reference model (when one is attached)7071A reference model is a triangle mesh of the real aircraft (3D scan or CAD72export). Read `docs/guidebook/13-reference-models.md`; it is the contract and73is tool-agnostic on purpose.74751. Accept only triangle meshes (STL, PLY, OBJ, 3MF, GLB/glTF, OFF). If the76 attachment is a native CAD, scan-project, or point-cloud file, stop and ask77 the user to export a triangle mesh from their tool with an explicit length78 unit, optionally with a `<stem>.reference.json` sidecar. Give no79 vendor-specific instructions; the repository does not know or care which80 tool produced the mesh.812. Establish the unit (`--units` or sidecar `units`), the source frame82 (`--axes`, open-air axis <- signed source axis), and one anchor dimension83 (`--expect-span-m`, or the sidecar's `measured_span_mm`). Never guess a84 unit: the anchor cross-check exists to abort on a wrong one.853. Dry-run first, from the repository root with the environment of section 5:8687 ```bash88 python -m openair.reference ingest <mesh> --concept <name> --units mm \89 --axes "<mapping>" --expect-span-m <anchor> \90 --treatment <reproduction|inspiration|requirement> \91 --out <staging>/reference --dry-run92 ```9394 View `reference-sections-dryrun.png`. Confirm the body edge excludes the95 wing, LE/TE stations follow the fitted lines, station envelopes match their96 fitted super-ellipses, airfoil sections have the expected thickness and97 camber sign, and fins sit on the deck. Fix `--axes`/`--datum` and repeat98 until the figure is right; then run without `--dry-run`, with99 `--sketch-dir <staging>` so the silhouettes land beside `design.yaml`.1004. Treat everything under `reference.json .suggested` as **measured101 (reference model)** with the tolerances in `.tolerances`: planform (span,102 root chord by centreline extrapolation, measured `wing.sections`, and their103 area/MAC-locus-equivalent sweep/taper/dihedral descriptors), body stations104 with section powers,105 fin geometry, `t_over_c` plus the NACA four-digit fit, and, when resolved,106 the hinge line and as-scanned control deflection. Read the `notes`, the107 per-station `fill_method`/`width_clamped`/`top_overridden` flags, and the108 `width_core_m` versus `width_blended_m` choice; decide deliberately and109 write the reason in the brief.1104a. For a reproduction with measured wing stations, copy the complete111 `suggested.wing.sections` list and its scalar equivalents together; never112 hand-pick one without re-deriving the other. Inspect113 `disclosures.wing_planform` and the solid section outline in114 `reference-sections.png`: confirm the body-exclusion width, mandatory115 root/straight-band/tip breakpoints, gross area, and simplification116 tolerance. Section-local t/c is an inferred absolute-thickness loft117 control, not another airfoil cut; keep the measured global118 `wing.t_over_c` for OAS/wingbox physics.119 For inspiration or requirement intent, pass that treatment to ingest;120 sections remain disclosed as a reproduction alternative but121 `suggested.wing` stays scalar and valid for MDO.1224aa. When `measurements.fairings.aft_shoulder.ok`, inspect its fin-point123 exclusion, fit RMS/acceptance, dimensional and contour simplification124 residuals, skin penetration, nominal/effective hidden skirt, support125 adjustment, total burial, and junction crease in126 `reference-sections.png`. For a reproduction copy the127 complete `suggested.fuselage.fairings` list; do not hand-tune its stations.128 `max_width_loc: -1` is the measured dome convention. Inspiration and129 requirement modes keep the candidate disclosed but do not emit it.1304b. When the fin measurement resolves a root junction, write its mirrored131 absolute y and shared z into `vtail.y_root_m/z_root_m` and set132 `vtail.root_attachment: measured`. The default `derived` mode intentionally133 ignores those coordinates and applies the legacy 60%-body rule; never use134 it for a measured reference-model reproduction. If the measured junction135 needs a shoulder fairing, require the generated fairing plus derived buried136 root extension; never project the exposed fin inward or relax attachment QA.1375. The scan silhouettes (`sketch-top/side/front.png`) are the primary views:138 orthographic, rectified by construction, 10 mm grid, mm/px in the PNG139 metadata. Keep any photographs or renders in the source list as secondary140 evidence only; never let a render overrule the scan.1416. What a reference model cannot supply stays placeholder or comes from the142 measurement documents: mass, CG, inertia, control travel and trimmed143 neutral, thrust, materials, solver constants. The as-scanned control144 deflection is a control position at scan time, not a trim.1456b. When the scan resolves a hinge line, write the control surface into146 `flight_dynamics.control_surfaces` (hinge → `chord_fraction`, first/last147 detection → span fractions, provenance `measured (reference model)`), put148 the measured travel in `max_up_deg`/`max_down_deg`, the flown neutral in149 `neutral_deg` (or `null` when nobody measured it), and the as-scanned150 position as the starting `trim_deflection_deg`. For a tailless airframe151 whose twist is a measurement, set `mission.pitch_trim_control: elevon` so152 the pipeline trims with the elevon instead of re-twisting the wing153 (guidebook chapters 03, 09). Trailing edge up is positive everywhere.1547. A reference-model reproduction defaults to `sketch.treatment:155 reproduction` with `hard_scale: 1.0`; use `inspiration` only when the156 intent asks for a redesign grounded on the scan.1578. Record in the brief: source file, sha256, declared unit, anchor check,158 axes mapping, symmetry residual, pitch rotation applied to reach the159 root-chord datum, shells dropped, and every scan weakness the ingest160 flagged (open noses, incomplete leading edges, repaired hatches, mirrored161 halves). The reference is measured design input; it is never validation162 truth.163164## 3. Measure before authoring165166Use a common coordinate convention: `x/L=0` at the nose, `x/L=1` at the tail,167positive `y` from centerline to wingtip, and a documented vertical datum for168`z`. Measure the silhouette, not shading or perspective margins.169170Record source, image-space endpoints/contour coordinates, method, scale,171value, tolerance, and provenance (`measured`, `measured (reference model)`,172`inferred`, or `defaulted`) for every item below. Pixel coordinates are173evidence, not false precision: label agent-read coordinates approximate and174preserve wider physical tolerances. When a reference model was ingested, its175measurement record replaces pixel reading for every quantity it covers; use176pixel measurements only for what the mesh does not show.177178### Planform179180- Fuselage length and full maximum width.181- Wing span, root chord, tip chord, taper, and wing-root leading-edge `x/L`.182- Leading-edge sweep with the schema sign convention:183 `atan((x_tip_LE - x_root_LE)/(span/2))`; forward sweep is negative.184- Tail span, root chord, sweep, cant, and longitudinal placement where visible.185 These measurements must become optional `sketch.fin_*` priors, not only186 prose in the worksheet.187188Compute and cross-check:189190```text191span_over_length = wing.span_m / fuselage.length_m192root_over_length = wing.root_chord_m / fuselage.length_m193taper = tip_chord_m / root_chord_m194x_le_root_over_length = wing.x_le_root_m / fuselage.length_m195```196197### Fuselage loft198199Use 6–8 shared `x/L` stations covering nose, forebody, maximum section,200wing/inlet transitions, aft deck, boattail, and tail tip.201202- From top view, measure the full body width at each station.203- From side view, measure upper and lower contours at the same stations.204 Set `height_m = z_top - z_bottom` and205 `z_offset_m = (z_top + z_bottom)/2` relative to the stated datum.206- Keep stations strictly increasing, with endpoints at 0 and 1. Interior207 stations must have positive width and height.208- Set `max_width_m` and `max_height_m` to the station maxima.209- If a front/cross-section view is absent, label section curvature inferred.210211Read the historical parameter contract in212`docs/history/2026-08-20-1942-super-ellipse-and-parameter-audit.md` before213choosing section powers. Use its supported split-super-ellipse range and start214from:215216```text217ellipse: side 2.0, top 2.0, bottom 2.0218wide knife blade: side about 1.2, top about 2.0, bottom about 2.0219bubble over hull: side about 1.6, top about 1.6, bottom about 5.0220slab / box: side 4–8, top 4–8, bottom 4–8221```222223Powers control section curvature, not top/side silhouette dimensions. Do not224invent unsupported canopy or inlet fields. A multi-section wing is permitted225only for a source-locked reproduction and only from measured/reference station226evidence; use the ingest-generated list rather than tracing arbitrary panels.227Record visible but still unrepresentable features as limitations in the brief.228229### Tolerance discipline230231- Give every image measurement a nonzero tolerance based on grid resolution,232 line thickness, rectification, and view ambiguity.233- Oblique/unrectified photos require wider bounds than orthographic drawings.234- Start conservatively; tighten `sketch:` tolerances only after a Studio235 re-trace supports it.236- Keep exact document values and unit conversions traceable to their source.237- Mark hidden-view dimensions, airfoil, twist, material gauges, solver238 constants, propulsion lapse/TSFC coefficients, and mass guesses as inferred239 or template-defaulted; sketches do not prove them.240241## 4. Author the source bundle242243Create a temporary sibling staging directory under `designs/` only after the244guard and source review. Author the complete bundle there. Before publication,245validate the YAML, concept name, brief markers, canonical PNG names/signatures,246and allowed file set (`design.yaml`, `brief.md`, `sketch-*.png`, and the247optional `reference/` directory with `reference.json`, `reference.ply`, and248`reference-sections.png`); also reject unchanged template placeholders such as249`new-aero-concept` or its starter notes. Publish with one same-filesystem250`os.replace(staging_dir, designs/<name>)` only while the target is still251absent. Remove the staging directory on any failure. Never expose a partially252written concept.253254The complete staged bundle contains:255256### `design.yaml`257258Start from `designs/_template/design.yaml`, keep every schema section, and:2592601. Set `name`, concise notes, measured `sketch:` ratios, and their tolerances.261 New sketch-authored concepts default to autonomous prior treatment:262263 ```yaml264 sketch:265 treatment: inspiration266 hard_scale: 3.0267 fidelity_weight: 1.0268 ```269270 One tolerance is the no-penalty visual envelope; `hard_scale × tolerance`271 is the immutable identity bound. Populate every measured272 `fin_span_m/fin_span_tol_m`,273 `fin_root_chord_m/fin_root_chord_tol_m`,274 `fin_le_sweep_deg/fin_le_sweep_tol_deg`,275 `fin_cant_deg/fin_cant_tol_deg`, and276 `fin_x_le_m/fin_x_le_tol_m` pair. Use `requirement` only when the user277 explicitly says the measured geometry must not depart.2782. Set wing, fuselage station loft and powers, tails, and placement from the279 measurement record.2803. Populate mission and published engine facts from the requirement sources,281 converting to SI and showing conversions in the brief. For example,282 `45 kgf = 441.299 N` and `1100 g/min = 0.0183333 kg/s`.2834. Use template values elsewhere. Do not retune advanced solver calibration284 from a sketch.2855. Keep payload and fuel locations physically inside the measured body and286 preserve their provenance/bounds in `sketch:`.2876. Do not add computed Pydantic fields or generated specifications under288 `designs/`.289290### `brief.md`291292Write, in order:2932941. Intent and configuration summary.2952. Source list, including view classification and output PNG mapping.2963. Requirement record with units, source, tolerance, and status.2974. Coordinate/scale/rectification method.2985. Measurement and inference record with value, tolerance, provenance, and299 rationale.3006. Defaults retained from the template, grouped by dotted path with rationale.3017. Visible unsupported features and expected fidelity limits.3028. Geometry-checkpoint iteration log.303304All durable source, measurement, and inference content must remain **outside**305these markers because a later Studio save replaces their contents:306307```text308<!-- OPENAIR_SKETCH_WORKSHEET_START -->309## Sketch measurement worksheet310Short generated-compatible summary of the current geometry.311<!-- OPENAIR_SKETCH_WORKSHEET_END -->312```313314Inside the worksheet, record unsupplied rectification honestly, for example315`not rectified (bootstrap — approximate agent image-space measurement)`.316Never fabricate four-point controls or grid scale. For scan silhouettes write317`orthographic projection of the reference mesh, <mm/px> mm/px, 10 mm grid318(rectified by construction)` and cite `reference.json`.319320## 5. Validate and run the bounded geometry loop321322Read `.cursor/skills/aero-qa-geometry/SKILL.md` and323`docs/guidebook/01-openvsp.md`. Activate the environment before Python starts:324325```bash326source .venv/bin/activate327export LD_LIBRARY_PATH="$PWD/tools/libs/usr/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH:-}"328export PATH="$PWD/tools/openvsp/opt/OpenVSP:${PATH:-}"329export PYTHONPATH="$PWD/src:${PYTHONPATH:-}"330export OPENMDAO_REPORTS=0331```332333Before each geometry run, validate the YAML through `VehicleSpec`:334335```bash336python -c 'import sys,yaml; from openair.schemas import VehicleSpec; VehicleSpec.model_validate(yaml.safe_load(open(sys.argv[1])))' "designs/<name>/design.yaml"337python -c 'import sys,yaml; from openair.schemas import VehicleSpec; from openair.reporting.report import _shape_fidelity; s=VehicleSpec.model_validate(yaml.safe_load(open(sys.argv[1]))); r=_shape_fidelity(s); assert r["ok"], r' "designs/<name>/design.yaml"338python -m openair.geometry run "designs/<name>"339```340341Run at most three total geometry iterations. After each run:3423431. Inspect `results/<name>/baseline/geometry.json`, not only top-level `ok`.344 Require:345 - `.openvsp.readback.matches_spec == true`346 - `.openvsp.stl_bbox.ok == true`347 - `.openvsp.mesh_checks.ok == true`348 - `.packing.ok == true`349 - `.openvsp.errors` is empty350 - `_shape_fidelity(spec)["ok"] == true`351 - when a reference model exists: `.reference_fidelity.available == true`352 and, for a `reproduction`, `.reference_fidelity.ok == true` (body p95353 surface deviation and top/side silhouette IoU inside the acceptance354 recorded in `reference.json`; wing/fin and whole-aircraft p95 are355 disclosed under `.reference_fidelity.disclosed`).3562. Open `results/<name>/baseline/threeview.png` beside all source sketches.357 Compare span/length, chord ratios, sweep sign/magnitude, wing station,358 fuselage top/side silhouettes, deck/belly centerline, and fin placement359 against the recorded tolerances. When a reference model exists, also open360 `results/<name>/baseline/reference_overlay.png` and read361 `reference_fidelity.silhouettes` (reference-only versus model-only area)362 and `.stations`/`.planform` deltas: every departure must correspond to a363 feature the brief already lists as unrepresentable (strakes, root blends,364 rounded tips, open hatches), never to a measurement you could correct.3653. Append the observed mismatch and source-level adjustment to the brief's366 iteration log. Adjust `design.yaml`, never result artifacts or367 `reference/`.3684. Repeat only when the source bundle changed. Stop when checks pass and the369 visible shape is within tolerance, or after iteration three.370371Packing is a real constraint, not permission to silently distort the sketch.372If the engine or payload cannot fit within measured tolerance, report the373conflict and the available upstream choices. If an artifact-truth check fails374for a tooling reason, report the blocker rather than weakening the check.375376## 6. Report and hand off377378Report:379380- files created;381- a concise table separating measured, measured (reference model), inferred,382 and defaulted values;383- remaining unsupported or low-confidence shape features, including every384 scan weakness the ingest flagged;385- geometry JSON evidence and whether the three-view is within tolerance;386- the baseline `threeview.png` inline, and `reference_overlay.png` with the387 `reference_fidelity` numbers when a reference model exists;388- whether the three-iteration limit was reached.389390State explicitly that initialization is a geometry checkpoint, not full391aircraft validation. In interactive mode, offer the live Studio for a visual392review and validated save. In explicitly autonomous/no-manual-review mode,393Studio review is optional: the measured bundle may proceed directly to394`/create-aero` after its source files are committed, and the inspiration-mode395MDO must correct suboptimal geometry while documenting departures. End with:396397```bash398python -m openair.designer <name> --open399# Or skip Studio in autonomous mode. After committing the source bundle:400/create-aero designs/<name>401```