Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
68d2bb7
feat(tools): spar bundle-fit tool; solve BOTH end stations for thickness
Stab-Rabbit-coding Aug 29, 2026
fdd522c
feat(wing): re-loft for the unified 20 mm FIXED structural spar (Rev T1)
Stab-Rabbit-coding Aug 29, 2026
c5c64cb
docs(wing): publish the Rev T1 attach interface; correct four upstrea…
Stab-Rabbit-coding Aug 29, 2026
c1cf427
chore(memory): mirror Rev T1 wing/fixed-spar memory per AGENTS.md aud…
Stab-Rabbit-coding Aug 29, 2026
e887b66
fix(wing): duct- and bay-bounded joints; reduction drive; re-derived …
Stab-Rabbit-coding Aug 30, 2026
c18a1b9
docs: describe the built section accurately; cite Part 23 correctly
Stab-Rabbit-coding Aug 30, 2026
53e2c56
fix(docs): sweep four stale ring-magnet/encoder figures missed in the…
Stab-Rabbit-coding Aug 30, 2026
e364ae3
chore(memory): mirror Rev T1b corrections per AGENTS.md auditability
Stab-Rabbit-coding Aug 30, 2026
1f4eadb
Merge branch 'claude/serenity-wing-nacelle-validation-kvux9w' of http…
Stab-Rabbit-coding Aug 30, 2026
16ebb59
feat(fuselage): build the Rev T1 wing-root joint and a multi-turn til…
Stab-Rabbit-coding Aug 30, 2026
385b1d9
chore(memory): mirror Rev T1c fuselage/tilt-drive memory per AGENTS.m…
Stab-Rabbit-coding Aug 30, 2026
7e1cc2e
docs(mass): audit cargo-section and wing-root weight; fix three BOM m…
Stab-Rabbit-coding Aug 30, 2026
e3e1b7d
docs(plan): ranked weight-reduction targets for the cargo section and…
Stab-Rabbit-coding Aug 30, 2026
fd331fb
chore(git): ignore Python virtualenvs
Stab-Rabbit-coding Aug 31, 2026
1a4abc3
Merge branch 'main' into claude/serenity-wing-nacelle-validation-kvux9w
Stab-Rabbit-coding Aug 31, 2026
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
20 changes: 20 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,26 @@ __pycache__/
*.pyc
*.pyo

# Python virtual environments (never commit). The local .venv here is 351 MB of
# third-party packages; a single `git add -A` would push the lot. Nothing under
# it has ever been tracked, so this is a guard rather than a cleanup.
#
# It also matters to CI: `.github/workflows/ci.yml` runs `flake8` with an
# explicit --exclude list that does NOT name .venv, so lint only passes today
# because CI checks out a fresh tree with no virtualenv in it. Were one ever
# committed, the lint job would immediately fail on thousands of findings in
# vendored code. (Locally, `flake8 .` does report those — run it over
# `git ls-files '*.py'` instead to see only this repo's own code.)
#
# NOTE for anyone running the tools: this .venv SHADOWS system Python packages
# the repo's tools rely on (manifold3d, sympy, matplotlib are installed
# system-wide). Invoke tools as `/usr/bin/python3 tools/<name>.py`, not through
# the venv.
.venv/
venv/
env/
ENV/

# Claude Code agent worktrees and session data
.claude/

Expand Down
3 changes: 3 additions & 0 deletions Browncoats-workspace.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
},
{
"path": "../Tactical-WX-RX"
},
{
"path": "../engineering-pe-skills"
}
],
"settings": {
Expand Down
718 changes: 647 additions & 71 deletions CLAUDE-MEMORY.md

Large diffs are not rendered by default.

30 changes: 19 additions & 11 deletions PROJECT_INDEX.md

Large diffs are not rendered by default.

118 changes: 114 additions & 4 deletions REFERENCES.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,65 @@ aft white); controlled by FC4 node (Simon's medbay, Bay D).

---

### REF-FAA-004: 14 CFR Part 23 — Airworthiness Standards: Normal Category Airplanes

| Field | Value |
|---|---|
| **Issuing authority** | U.S. Federal Aviation Administration (FAA), Department of Transportation |
| **Current edition** | Part 23 as restructured by Amdt. 23-64 (effective 2017-08-30), performance-based; as amended through the 2024 annual CFR edition |
| **Official URL** | <https://www.ecfr.gov/current/title-14/chapter-I/subchapter-C/part-23> |
| **Verified source** | Section text quoted below was retrieved and verified verbatim 2026-08-29 from GovInfo's authoritative CFR XML — <https://www.govinfo.gov/content/pkg/CFR-2024-title14-vol1/xml/CFR-2024-title14-vol1-sec23-2230.xml> and <https://www.govinfo.gov/content/pkg/CFR-2024-title14-vol1/xml/CFR-2024-title14-vol1-sec23-2265.xml>. (eCFR's HTML endpoint bot-blocks automated retrieval; GovInfo serves the same authority.) |
| **Applicability caveat** | Part 23 governs **manned** normal-category airplanes. Serenity is an sUAS operated under Part 107 [REF-FAA-002], which imposes **no** structural certification basis. Part 23 is cited here as an **adopted engineering baseline**, exactly as `docs/structural_analysis.md` §3 already frames it — **NOT as a compliance claim.** |

**Sections applied in this project:**

| Section | Title | Applied where |
|---|---|---|
| **§ 23.2230** | *Limit and ultimate loads* | The 1.5× ultimate/limit factor used throughout `docs/structural_analysis.md` §3 and `tools/wing_spar_carrythrough.py` |
| **§ 23.2265** | *Special factors of safety* | Justifies an additional factor on FDM-printed structure — see below |

**§ 23.2230 (verbatim, GovInfo 2024 CFR):** the applicant must determine —
(a) *"The limit loads, which are equal to the structural design loads unless
otherwise specified elsewhere in this part"*; and (b) *"The ultimate loads,
which are equal to the limit loads multiplied by a 1.5 factor of safety unless
otherwise specified elsewhere in this part."*

**§ 23.2265 (verbatim, GovInfo 2024 CFR):** (a) *"The applicant must determine a
special factor of safety for each critical design value for each part, article,
or assembly for which that critical design value is uncertain, and for each
part, article, or assembly that is —"* … (a)(2) *"Subject to appreciable
variability because of uncertainties in manufacturing processes or inspection
methods."* (c) *"The applicant must multiply the highest pertinent special
factor of safety in the design for each part of the structure by each limit and
ultimate load…"*

**Why §23.2265 matters here.** Serenity's primary structure is FDM-printed
CF-PETG. Layer adhesion, raster orientation, moisture uptake, and
machine-to-machine variation are precisely the *"appreciable variability because
of uncertainties in manufacturing processes"* that (a)(2) contemplates. This is
the regulatory hook for the FOS 4.0 joint target that `docs/structural_analysis.md`
§3 currently describes only as *"a design-team judgment value"* — the judgment
is sound and now has a citable basis, though the specific numeric value remains
the project's own choice rather than anything Part 23 prescribes.

**CORRECTION THIS ENTRY MAKES — stale section number.**
`docs/structural_analysis.md` cited **"14 CFR Part 23.303"** in two places. That
section belonged to the **pre-2017** Part 23 and does not exist in the current
rule; the 2017 restructure moved the limit/ultimate relationship to **§23.2230**.
This is the same class of defect this file already recorded for §23.1401 (see
"Removed / Superseded Citations"). Both occurrences corrected 2026-08-29.

**Also worth recording, to prevent a future fabrication:** the load factors
**+3.8 / −1.52**, widely quoted as "the Part 23 load factors," appear **nowhere
in the current rule** — they belong to the pre-2017 §23.337. Current §23.2200(b)
requires only *"design maneuvering load factors not less than those, which
service history shows, may occur within the structural design envelope."* This
project's 4 g limit factor is an adopted figure under that framing, not a
regulatory quotation. Do not cite +3.8/−1.52 to current Part 23.

**Used in:** `docs/structural_analysis.md` §2, §3;
`docs/WING_ATTACH_INTERFACE.md` §2.1; `tools/wing_spar_carrythrough.py`

## Part II — United States Federal Communications Commission Regulations

> "Can't stop the signal." — Mr. Universe. We can, however, stay inside Part 15/95 limits while we transmit it.
Expand Down Expand Up @@ -1185,6 +1244,47 @@ FEA cross-check (ANSYS Workbench, linear-elastic model, Table 11): simulated fle

**Used in:** `airframe/README.md` §5.1

### REF-MATH-001: Melissen, J.B.M. — "Packing and Covering with Circles"

| Field | Value |
|---|---|
| **Author** | Johannes Bernardus Marinus Melissen, Utrecht University |
| **Publication** | PhD thesis, Universiteit Utrecht, 1997 |
| **Official URL** | <https://dspace.library.uu.nl/handle/1874/25091> — Utrecht University Repository, open access |
| **Retrieved** | 2026-08-29 |
| **Scope applied** | The proven-optimal ratios for packing *n* equal circles inside the smallest enclosing circle, for *n* ≤ 7. Only these small-*n* cases are used; they are proven optimal in this source and are reproduced throughout the standard circle-packing literature. |

**Values used (enclosing diameter ÷ single-circle diameter):**

| *n* | Ratio K(*n*) | Closed form |
|---|---|---|
| 1 | 1.00000 | 1 |
| 2 | 2.00000 | 2 |
| 3 | 2.15470 | 1 + 2/√3 |
| 4 | **2.41421** | **1 + √2** |
| 5 | 2.70130 | 1 + √(2(1 + 1/√5)) |
| 6 | 3.00000 | 3 |
| 7 | 3.00000 | 3 (hexagonal + centre) |

**Why this is catalogued rather than treated as common knowledge:** the *n* = 4
case decided a load-bearing geometry change. Two independent sources — the
owner's `docs/plans/2026-08-27-nacelle-wiring-plan.md` and the external Gemini
conversation it derived from — both specified an 11.0 mm spar bore for four
10 AWG conductors. Four Ø5.5 mm circles circumscribe **13.28 mm** at zero
clearance, so 11.0 mm does not fit at all, and the error propagated because the
constant was carried in prose rather than computed. It is now computed, from
this table, in `tools/spar_bundle_fit.py`, which refuses to interpolate for any
*n* outside the tabulated set.

**Caveat on the input, not the ratio:** the ratio is exact; the 5.5 mm wire OD
it is applied to is **not** a verified figure. `current-specification/bom_revS.csv`
records no outside diameter for `WIRE-10AWG`. See `tools/spar_bundle_fit.py`,
which prints that caveat on every run.

**Used in:** `tools/spar_bundle_fit.py`;
`airframe/openscad/wings/wings_s1223_revo.scad` (`SPAR_BORE_OD` derivation);
`docs/WING_ATTACH_INTERFACE.md` §2

## Part XI — FDA / CDRH Laser Product Regulations

### REF-FDA-001: 21 CFR Part 1040 — Performance Standards for Light-Emitting Products
Expand Down Expand Up @@ -1706,10 +1806,20 @@ Per-application operating mode differs even though the hardware is now identical
| Application | Qty | Mode | Range |
|---|---|---|---|
| Cargo winch | 1 | Continuous rotation, gateway closes position on the AK7455 spool encoder (REF-SENSOR-008) | Multi-turn, unbounded by the servo itself |
| Nacelle tilt | 2 | Position, firmware soft-limited | −5°…140°, backstopped by the existing CF-PETG hard-stop blocks in the external gear train (`docs/NOZZLE_DRIVE_TRADE.md`) — mechanically independent of the servo's own (now-removed) rotation pin |

Removing the pin on all three is a deliberate commonality choice, not a requirement of the
position-mode applications: LibreServo replaces the servo's potentiometer with a 360°
| Nacelle tilt | 2 | **CORRECTED Rev T1c (2026-08-30):** continuous rotation, Pilot closes position on the AK7455 nacelle encoder (REF-SENSOR-008) — the same pattern as the winch above | **Multi-turn** (1.438 rev of actuator per 145° of nacelle), unbounded by the servo itself. Soft-limited to −5°…140° *at the nacelle*, backstopped by CF-PETG hard stops in the external gear train |

> **The row above changed at Rev T1c and the change is structural, not editorial.**
> The tilt stage became a REDUCTION (tip 14T/50T, `i` = 3.571), so the drive shaft must
> turn **1.438 revolutions** over the 145° sweep and no limited-rotation servo can drive
> it at any horn radius. Removing the rotation pin is therefore **required** on the tilt
> servos now, not merely convenient — and the AK7455 became **load-bearing for control**
> rather than telemetry, because a multi-turn drive without absolute feedback does not
> know where the nacelle is. See `docs/WING_ATTACH_INTERFACE.md` §4.3b/§4.3c and
> `docs/TILT_DRIVE_CONTROL_SPEC.md`.

Removing the pin on the winch is a deliberate commonality choice; on the tilt servos it
is now a requirement (see the note above). It is not a requirement of the
position-mode applications generally: LibreServo replaces the servo's potentiometer with a 360°
absolute magnetic encoder (AEAT-8800, 16-bit), so position feedback and soft-limit
enforcement no longer depend on the mechanical stop the pin used to provide. See
REF-SENSOR-013/014/015 below for the individual part records, and
Expand Down
98 changes: 98 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,104 @@
- [ ] Verify AK7455 off-axis geometry + pinout vs datasheet (REF-SENSOR-*)
- [ ] ASTM D3039/D695 coupon test: CF-PLATE-2MM bending allowable (thwarts
built at FOS 8.5/8.7 vs the conservative 300 MPa stand-in only)
- [ ] **ASTM D3039/D695 certificate for the 20 x 16.3 CF SPAR TUBE.** New at
Rev T1 and now load-bearing: the spar is the wing's primary bending
member at FOS 9.0 against the same unverified 300 MPa stand-in
(`docs/TILT_SPAR_ANALYSIS.md` §3.6.3). The 4130 rows above no longer
govern the flight load path.
- [ ] **Measure the procured 10 AWG silicone wire OD.** `bom_revS.csv` records
none; the 5.5 mm figure the Ø20.4 spar bore is derived from is an
ASSUMPTION. A larger real OD re-opens the airfoil trade
(`tools/spar_bundle_fit.py` prints this caveat on every run).
- [x] **Tilt servo angular range (180 vs 270 deg) — CLOSED 2026-08-29, VOID.**
Owner direction: the drive turns the shaft MORE THAN ONE REVOLUTION, so
the stage is a reduction and the actuator's own travel no longer sets the
ratio. Built: module 0.8, 14T pinion / 50T ring, i 3.571, shaft 1.389 rev
per 140 deg, C 25.6 -> station 53.6.
- [ ] **ACTUATOR RE-SELECT (replaces the item above).** A multi-turn output means
the tilt drive is no longer a limited-rotation servo but a
continuous-rotation gearmotor or stepper, closed on the AK7455's absolute
nacelle angle. The DS3225 is ~17x oversized on torque AND now the wrong
kind of device. NOTE this makes the encoder load-bearing for CONTROL, not
telemetry: a multi-turn drive without absolute feedback does not know
where the nacelle is.
- [ ] **LG-11 coupon — DEMOTED at the wing root, still a gate elsewhere.**
Owner ruled the cargo bay clear, so the root joint was re-designed around
it: socket for shear + bonded 80x60 flange for the moment, FOS 29.2 at the
STANDING 5 MPa figure (29.2 / 87.6 / 274.6 at 5 / 15 / 47 MPa). The coupon
no longer decides whether that joint is buildable, only how small the
flange could shrink. It remains a gate for the tenon path and the thwarts.
- [ ] **Aero revalidation of the re-lofted wing (CFD or bench).** The section
is no longer S1223 -- root t/c 12.14 -> 17.72 %, tip 18.93 -> 26.70 %.
Every aero figure in this repo citing this wing is unverified until this
lands, including the 7.6 N cruise-lift figure and everything derived
from it. The built sections are designated S1223/t17.7 (root) and
S1223/t26.7 (tip) -- S1223's CAMBER LINE with the thickness envelope
scaled x1.46 / x2.20; camber is unscaled and exact (8.67% at 49.0%
chord), so zero-lift angle and lift-curve slope partially survive at the
ROOT on thin-airfoil grounds and not at all at the tip. CL_max, L/D and
the cruise-lift figure do NOT survive. Needs XFOIL or a
TRANSITION-SENSITIVE RANS run at Re 1.3-1.8e5 -- a fully-turbulent model
will misrepresent the separation bubble. `tools/wing_cfd_openfoam.py` is
still blocked on mesh generation. See docs/flight_envelope.md's banner.

#### 0.8.1 — Wing attach interface (Rev T1), open requirements

→ detail: `docs/WING_ATTACH_INTERFACE.md` §5; fuselage detail:
`airframe/fuselage-mid/WBS.md` §1.1.1.5

Wing side is BUILT. These are the two joints it publishes.

- [x] WA-R1/R1b, R2, R4, R6 — fuselage side BUILT 2026-08-30 (Rev T1c). Socket
Y +21.00 / Z +66.85 / D20.4 / 18.5 mm; F688ZZ and both tie rods deleted;
mortise 30.8 -> 12.8 (tenon fits +0.40 mm/side); nav D4.2, AK7455 D7.5 and
shaft D4.4 conduits cut. `wing_root_deconflict.py` now CLEAR.
- [x] WA-R15 — tilt actuator: DS3225 + LibreServo_v4 run MULTI-TURN, closed on
the AK7455; fuselage spur stage m0.8 38T/38T, C 30.40, 1:1. Coaxial does
not fit and no gear clears the tenon in Y -> 18 mm actuator standoff.
- [ ] WA-R3/R17 — split-collar pinch clamp is still not a part (no SCAD, no STL,
no BOM row). **BLOCKS wing removal/refit.**
- [ ] WA-R16 — the tilt train is NOT self-locking and has no holding provision.
**BLOCKS flight release.** `docs/TILT_DRIVE_CONTROL_SPEC.md` §5.2/§7.3.
- [ ] WA-R18 — Rev T1c is +102.8 g (+2.63 % AUW, revised by the weight audit);
hover T/W was ~1.19 vs a 1.2 minimum. Re-derive mass/CG/T-W.
**BLOCKS flight release.**
- [ ] MA-1 — BOM printed-part masses understate by +521.6 g (13.3 % of AUW)
across 23 rows measured against their STLs. Reconcile + add a CI check.
**BLOCKS any weight statement.** -> `docs/MASS_AUDIT_CARGO_WING_ROOT.md`
- [ ] MA-5 — hollow the actuator standoffs, -32.9 g, no structural question
(deflection 1.4e-5 mm at the gear mesh against a 0.05 mm budget).
- [ ] MA-6 — `PRINT-BATT-TRAY` measures 140.2 g against a 22 g BOM row.
- [ ] MA-7 — BOM mass column mixes installed mass, stock and GCS; add an
`Installed` flag before any weight statement uses it.
- [ ] W1..W8 — ranked weight-reduction targets: battery -225 g, tray floor
-23.1 g, actuator standoffs -32.9 g, cradle ~-25 g; wing root CLOSED.
W2 (BOM reconciliation) gates all of them.
-> `docs/plans/2026-08-30-001-weight-reduction-targets-plan.md`
- [ ] WA-R15a — re-measure the cargo-bay roof band: the actuators now reach
X -158.5 / -221.5 at Z +85.99..+112.99.
- [ ] TILT-CTL-01..06 — tilt control loop open items (plant model, slew rate,
differential-tilt trip, LibreServo_v4 encoder part).
→ `docs/TILT_DRIVE_CONTROL_SPEC.md` §8.
- [ ] WA-R7..R12 — nacelle: trunnion bearing bore D20.0 at ring plane X ~ 28
(axial AND radial duty), ring gear PD 33.8 at C 26.0, ring magnet
ID 27 / OD 41 axially separated from that gear, the 4 x 10 AWG
disconnect relocated into the nacelle annulus, the nav 3-core crossing
at the trunnion, and confirmation of the 32 mm spar-stub protrusion.
- [ ] WA-R13 — avionics: `docs/TILT_ENCODER_WIRING_EMI_SPEC.md` §6.1's
ferromagnetic-spar premise is corrected in place; confirm the firmware
zero-calibration procedure still covers the drive-shaft/pinion field
that replaces it.
- [x] **OWNER DECISION — cargo-bay intrusion: CLOSED 2026-08-29.** The bay stays
clear; nothing goes inboard of hull X ~ -86 against a bay edge at -100.
The constraint produced a better joint (moment FOS 4.02 -> 29.2), not a
compromise. See `airframe/fuselage-mid/WBS.md` §1.1.1.5.
- [ ] **Spar stub / trunnion packaging — NEW, tightest constraint on the joint.**
The spar must terminate >= 26 mm from the nacelle duct axis, so the stub is
15.0 mm (max 15.7). The trunnion bearing PAIR, the 50T ring gear and the
ID26/OD41.2 ring magnet must all fit inside that 15 mm, and the magnet and
gear are nearly coradial (r 13.0-20.6 vs 20.0) so they need axial
separation. 2x 6804 (20x32x7) = 14.0 mm fits; MF128ZZ retired to QTY 0.

### 0.10 Update and correct documentation touching every non-archived file.

Expand Down
Loading
Loading