# LASER LESSONS (ComMarker B4 60W MOPA + LightBurn)

## Source: `bot-context.md`

# Laser Bot Operator Handbook (public)
Read this first, then the lessons page ([/lessons](/lessons)). Be token-efficient. The owner presses Start. The bot never does.

## 1. Machine
- ComMarker B4 60 W MOPA fiber (JPT-class source), JCZ USB-Lite controller, LightBurn 1.7.08.
- 110 mm lens, 110x110 field, correction file jcz110.cor. **Job centre = 55,55.** 63,63 is obsolete.
- Galvo calibration was finalised 2026-10-15. The calibration kit and its history live in the calibration folder (B4_CALIBRATION_KIT).

## 2. Loading a file into LightBurn safely
1. Check the LightBurn window title. A `*` means unsaved changes. **Ask the owner before discarding them**, unless the owner names that project to discard.
2. If LightBurn has to restart, find its PID with `ps` + `awk` and kill only that PID. **Never `pkill -f`**, because it can match other processes.
3. Relaunch detached (`nohup setsid lightburn <file> &`) so it survives the shell.
4. **Never press Start. Never touch LightBurn while a job is burning.** If the owner says they will load the file, don't close or relaunch anything.
5. "Cut Selected Graphics" is on, so the owner presses Ctrl+A before Start.

## 3. Folder layout (laser root)
- `coins/` coin jobs (recovery, brass, lion_portrait, ...). The bot's work goes in `grok/` subfolders.
- `washers/` washer designs and colour tests.
- `colortest/` colour calibration (`ss245_rgb/` = 8-face RGB tester).
- `tools/` scripts (below). `libraries/` LightBurn libraries (`grok/HD_fill_black.clb`).
- `calibration/` galvo and colour calibration kits. `pre55/` backups from before the 55,55 recentre and old ss245 outputs.
- `LASER_LESSONS.md` (lessons, read before every job), `INDEX.md` / `MANIFEST.csv` (file index).

## 4. Tools
- `recenter55.py` recentres projects from 63,63 to 55,55 (keeps `<name>.pre55.lbrn2`). `--dry` audits without writing.
- `to_ss245.py <file|folder>` makes `<name>_ss245.lbrn2` (24.5 mm polished stainless, centre 55,55, colours from the palette, deep stacks collapsed into one layer per colour). `--map PATTERN=key` overrides a role. `--hd-black` writes `*_ss245_hdblack.lbrn2`.
- `est_time.py <files>` gives a rough burn time (filled area / interval / speed x passes x crosshatch + 15%).
- `dump_layers.py <folder>` writes a `_LAYERS.txt` for every .lbrn2.
- `brass_rules.py` `apply()` adds the brass CLEAN/POLISH layers idempotently.
- `ss_color_palette.json` holds the stainless colour presets plus verification status and observed large-area colours.
- `gen_ss245_rgb.py` (in colortest/ss245_rgb) regenerates the RGB tester and its plan CSV.

## 5. Design rules
- The design (letters/logo) is RAISED and unburned. The field inside the work circle is DEEP-ETCHED. Outside the work circle is transparent: nothing burns there, and no background, glow or haze.
- Brass recovery coin: 39.5 mm with a lip, so the work circle is 37.5 mm.
- Traces: copy clean shapes and don't redraw. Remove specks and glow, and keep clean gaps. QC whole letters, bottoms included, against the source.
- Every .lbrn2 gets a matching `_LAYERS.txt` and an output-off FRAME layer.
- Never edit another agent's (Claude's) files. Write new files and keep the originals.
- Christian designs: Baptist-friendly, no crosses, understated.

## 6. Material rules
**Brass/copper deep engraving:** insert a CLEAN (20 %, 1500 mm/s, 100 kHz, 200 ns, 0.01 x2, crosshatch) after every 5 deep passes. The LAST layer is a full-surface POLISH (18 %, 2000 mm/s, 350 kHz, 10 ns, 0.01). Never use these on stainless, polished or anodized pieces.
**Black-field brass order:** (1) deep engraving + CLEANs + POLISH; (2) BLACK on the field only (40 %, 500, 40 kHz, 200 ns, 0.02 x2, untested); (3) final LETTER CLEAN on the raised letters and rings only (brass CLEAN settings, x1).
**Stainless colour = surface mark:** use one lean layer per colour, with a separate layer for each shade. Never copy brass deep stacks.
- HD fill black (14 purple layers + 2 blue facets, ~130 min per coin, glossy black) is used only on purpose.
- For black fields, use **4 passes of the HD-black purple setting** (15 %, 567, 280 kHz, 80 ns, 0.004, crosshatch x2, angles 0/45/90/135), about 14 min.
- The hard blacks (20 %/567 and 30 %/300/200 ns) **spark and burn on fields**. Keep them for small marks and lines.
- Big areas run hotter and paler than test cells. Keep colour tests at 30 % or less.
- Anodized aluminium black: 12 %, 1500 mm/s, 50 kHz, 0.045, 1 pass. Brass colours are unverified, so flag heat and cool between passes.

## 7. Verified stainless colours (polished, by eye)
| Preset | Settings (crosshatch, x2) | Test cell | Large field (2026-10-15) | Mapping confidence |
|---|---|---|---|---|
| purple R1-0106 | 15 %, 567, 280 kHz, 80 ns, 0.004 | deep purple-black | lavender / light mauve | medium |
| deep blue R1-0805 | 7.5 %, 700, 119 kHz, 60 ns, 0.005 | deep blue | slate blue-grey | medium-low |
| blue R1-0904 | 15 %, 1200, 230 kHz, 60 ns, 0.005 | good blue | pale grey-green / silver | medium |
| black (washer) | 20 %, 567, 280 kHz, 80 ns, 0.004 | black | brown-black, sparks, avoid on fields | high |
| black lines | 30 %, 300, 50 kHz, 200 ns, 0.01 | dark lines | brown-black, sparks | high |
| gold R1-1202 | 48.4 %, 317, 61.5 kHz, 60 ns, 0.0287 | untested | never fired (layer was off) | n/a |
Energy-density model: E = W / (speed x interval) J/mm², W = power% x 60 W. Dose = E x 2 (crosshatch) x passes.

## 8. Open work
- The RGB 8-face tester (4 coins, 26 cells per face, plan CSV, ~21 min total) is ready and not burned.
- The colorfield v2 coin (gold removed, black wedges = 4-pass HD black, ~14 min) is ready and not burned.
- Gold is still untested. Whether purple came out lavender and deep blue came out slate, or the other way round, is uncertain; a single swatch of each would confirm it.

## 9. Site (laserview.hankelsner.tech)
- [`/rules/`](/rules/) — public rules tree. HTML pages live at `/rules/<page>/`; raw markdown at `/rules/<path>.md`; machine index at [`/rules/index.json`](/rules/index.json).
- [`/lessons`](/lessons) — combined lessons HTML; raw combined dump at [`/lessons.md`](/lessons.md).
- [`/color/`](/color/) — MOPA colour grids and data (`b4_measured.json`, `color_settings.json`, rounds).
- [`/projectaddons/`](/projectaddons/) — motorized Z / camera / Pi+Pico add-ons (older copy also at [`/workup/`](/workup/)).
- [`/settings/`](/settings/) — material settings index; [`/tools/`](/tools/) — tools index.
- [`/plates/`](/plates/) — colour calibration plates; public JSON at `/api/materials`, `/api/plates`, `/api/cite` (see [Colour plates API](api.md)). Unified browser on [`/color/`](/color/) and [`/colors/`](/colors/); cite **Plate 31, A8**.
- Source markdown on the VPS: `/srv/web/laserview.hankelsner.tech/rules-src/`. Publish with `laser-rules-build`.
- The site is hosted by the VPS bot. Send content to the VPS agent, which publishes it. The laser bot doesn't edit the site directly.

## Colour DB v3 (cut settings + sub-layers)
- One colour = one LightBurn layer; multi-pass stacks use `sublayers[]` (HD fill black = 16).
- Full Cut Settings Editor fields live in `cut_settings` + each sub-layer. Site browsers show/filter/edit them (Hank-gated writes).
- `GET /api/library.clb` exports one Entry per colour with sibling CutSettings per sub-layer.
- **Sub-layer .clb/.lbrn2 serialization is UNVERIFIED** until Hank does one LightBurn open-test. >11 sub-layers may need a split. Do not present exports as verified.


## Source: `machine.md`

# Machine

- ComMarker B4 60W MOPA, JCZ USB-Lite, LightBurn 1.7.08.
- 110 mm lens: field 110×110, `jcz110.cor`, job center 55,55 (63,63 is obsolete).
- Galvo values live in LightBurn `prefs.ini`; when a `.cor` is loaded, bulge/skew/trapezoid show greyed out but still apply.


## Source: `workflow.md`

# Workflow

- Fix root causes (calibrate the galvo) rather than working around them.
- Every project gets an output-off FRAME layer for alignment.
- Every `.lbrn2` ships with a `<name>_LAYERS.txt` listing each layer's settings, made by `tools/dump_layers.py <folder>`.
- Each AI's work goes in its own subfolder (`grok/`, `claude/`, `hank/`); never edit another AI's files.
- A human presses Start; bots never do.
- Never discard an open project with unsaved changes unless the owner names it.


## Source: `design/coins.md`

# Coins / emblems (get the negative right)

- The DESIGN (letters/logo) is RAISED: the highest point, unburned (white = no burn).
- The FIELD inside the work circle is DEEP-ETCHED (black = deepest, most passes, rotating hatch).
- OUTSIDE the work circle is fully transparent and nothing burns: no background image, glow, haze or fill.
- Example: a 39.5 mm brass coin with a lip leaves a 37.5 mm work circle.
- Tracing a photo logo: copy a clean trace of the shapes and don't redraw or get fancy. Remove glow, streaks and specks (especially at letter feet). Keep clean gaps between letters and rings.
- QC: zoom in on every whole letter, bottoms included, against the source before burning.
- Hiding an old mark: deep coarse crosshatch with a large dot/line width in the field.
- Low-poly art: burn the facet edges as thin lines (mesh look).
- Black-field brass coins: deep + polish, then field-only black mark, then letter-only final clean — full layer order and settings in [Black-field brass coins](../materials/brass-copper.md#black-field-brass-coins) (**UNTESTED**).


## Source: `materials/brass-copper.md`

# Brass / copper deep engraving

**ONLY these materials for this deep-etch recipe; never stainless, polished or anodized.**

- After every 5 deep-etch passes, add a CLEAN layer: 20%, 1500 mm/s, 100 kHz, 200 ns, 0.01 mm, bidirectional crosshatch, 2 passes, whole coin.
- The LAST layer is a full-surface POLISH (output on): 18%, 2000 mm/s, 350 kHz, 10 ns, 0.01 mm, letters included, covering the entire coin to even out edges and clear debris.
- Sources: the [ComMarker B6 MOPA brass blog](https://www.commarker.com/archives/49730) and [lahobbyguy t=8237](https://forum.lightburnsoftware.com/t/8237).
- Deep brass settings are **UNTESTED**. Heat builds fast, so cool between passes.

## Black-field brass coins

Layer index is run order (**UNTESTED**):

1. **All deep engraving** — CLEAN after every 5 deep passes, ending with the full-surface POLISH (settings above).
2. **BLACK mark** on the etched field only: 40%, 500 mm/s, 40 kHz, 200 ns, 0.02 mm, ×2 crosshatch (source [omglaser.com/laser-settings](https://omglaser.com/laser-settings) #59).
3. **FINAL LETTER CLEAN** on the raised letters and rings only: 20%, 1500 mm/s, 100 kHz, 200 ns, 0.01 mm, ×1 (source [blog.commarker.com/archives/49730](https://blog.commarker.com/archives/49730)). Brightens letters and removes black overspray. **Never** run it over the black field.


## Source: `materials/stainless-polished.md`

# Polished stainless

- MOPA colours: only from eye-verified test cells, and only on polished stainless. Plain stainless goes black instead.
- Large areas run hotter than small test cells.
- See also [Color](../color.md) and the live [/color](/color/) grid data.
- Stainless colour = surface mark: use one layer per colour with the verified pass count, and never copy brass deep-pass stacks. The exception is the verified HD preset below.

## High-definition fill black (**verified**, Hank)

Opt-in via `to_ss245 --hd-black` (lean version is the default). Very good deep **glossy** black finish (verified by Hank), but slow.

1. **14 identical R1-0106 field layers** run in order: 15%, 567 mm/s, 280 kHz, 80 ns, 0.004 mm, crosshatch, ×2; angles 25, 163, 64, 74, 117, 132, 151, 155, 27, 154, 6, 86, 176, 147.
2. **2 R1-0904 blue facet layers**: 15%, 1200 mm/s, 230 kHz, 60 ns, 0.005 mm, ×2, 45°/135°.


## Source: `materials/stainless-plain.md`

# Plain stainless

- Black: 20%, 567 mm/s, 280 kHz, 80 ns, 0.004 interval, 2 passes (**verified**).
- Lines: 30%, 300 mm/s, 50 kHz, 200 ns, 2 passes (**verified**).


## Source: `materials/anodized-aluminum.md`

# Anodized aluminum

- Black anodized aluminum: 12%, 1500 mm/s, 50 kHz, 1 pass, 0.045 mm interval (**verified**).


## Source: `materials/color.md`

# MOPA colour on polished stainless: notes and RGB test plan (2026-10-15)
Machine: ComMarker B4 60 W MOPA, 110 mm lens, LightBurn 1.7. Material: 24.5 mm polished stainless coins.

## Colour model
Oxide-film interference; thickness sets colour (straw/gold, brown, purple, blue, then 2nd order pale gold, red/magenta, green, then grey/black). Main control: energy density E = W/(speed x interval) J/mm², W = power% x 60 W; crosshatch and passes multiply dose. Pulse width and frequency set pulse energy (W/f) and peak power; longer pulses run warmer. High pulse energy or slow high E causes sparks/burning. Large fills run hotter than small test cells.

## Verified by eye
- Purple R1-0106: 15%, 567 mm/s, 280 kHz, 80 ns, 0.004, crosshatch x2 (E≈3.97)
- Deep blue R1-0805: 7.5%, 700, 119 kHz, 60 ns, 0.005, x2 (E≈1.29)
- Blue R1-0904: 15%, 1200, 230 kHz, 60 ns, 0.005, x2 (E≈1.50)
- HD fill black: 14 purple-setting layers at rotating angles + 2 blue facet layers; glossy black, ~130 min per coin.

## Lessons 2026-10-15
- Hard black (20%, 567 mm/s) sparked and burned on a colour-field coin. For black fields use 4 passes of the HD-black purple setting at 0/45/90/135 (~14 min per coin).
- Gold R1-1202 was output-off in that burn and never fired, so gold is **UNTESTED** (it did not fail to show).

## Verified by Hank 2026-10-15 on large field wedges (24.5mm polished SS)
- Lavender/light purple: 15%, 567 mm/s, 280 kHz, 80 ns, 0.004, crosshatch x2
- Slate blue-grey: 7.5%, 700 mm/s, 119 kHz, 60 ns, 0.005, x2
- Pale grey-green/silver: 15%, 1200 mm/s, 230 kHz, 60 ns, 0.005, x2
- Brown-black with sparks/burned edges: 20%, 567, 280 kHz, 80 ns, 0.004 x2, and 30%, 300, 50 kHz, 200 ns, 0.01 x2. Avoid these on fields.

Note: big areas came out much paler than the small test cells (large fills run hotter). The purple vs slate-blue mapping could be swapped (medium-low confidence).

## Published starting points (other machines; scale before use)
- Red: 45%, 1000 mm/s, 60 ns, 400 kHz, 0.02 (30 W JPT, 110 mm) hobbyistlaser.com/blog/color-marking-stainless-mopa-settings
- Gold: 35%, 1000, 80 ns, 800 kHz, 0.02 (same)
- Blue: 40%, 1500, 100 ns, 600 kHz, 0.02 (same)
- Red: 27%, 800, 300 kHz, 60 ns, 0.003 (60 W JPT, 210 mm) forum.lightburnsoftware.com/t/experiences-with-color-marking/125488
- Green: 200 ns, 70 kHz, 25%, 600 mm/s (60 W JPT) anypowerrun.com/post/detail/1313/
- Gold bands 140-200 ns 200-260 kHz; green 420-500 ns 40-60 kHz (20 W) stylecnc.com/blog/mopa-color-laser-engraving-settings-stainless-steel.html
- Line interval matters more than speed/power; red and green are hardest on 110 mm: forum.lightburnsoftware.com/t/mopa-colours-hunting-for-a-good-red-and-green-on-brushed-stainless/136015
- Power % scales with wattage; ns, kHz and speed don't: mopacolorstudio.com/utilities/mopa-color-reference-chart.html

Scaling: halve power % of a 30 W recipe for 60 W; 110 mm lens has a smaller spot, so start about x0.8 and sweep.

## RGB calibration test (8 faces = 4 coins front and back, 26 labelled 2.2 mm cells each, power 25% or less)
F1 E sweep 0.5-16, 80 ns, 1 pass. F2 same, 2 passes, E 0.5-8. F3 E 0.5-16, 60 ns, 230 kHz. F4 forum-red geometry, E 2.5-16, 1 and 2 passes. F5 pulse width 2-200 ns. F6 frequency 30-800 kHz at 60/200 ns. F7 200/350/500 ns warm/gold plus published gold and green. F8 verified colours at x0.7/1/1.4/2 plus published reds. About 21 min total. Results get photographed under fixed white light and fitted to colour = f(dose, ns, f).


## Source: `color.md`

# Color

MOPA color work is only meaningful on **polished stainless**, with eye-verified test cells. Unpolished stainless goes black; large areas run hotter than small cells.

## Notes and test plan

- [MOPA colour on polished stainless](materials/color.md) — verified colours, lessons, published starting points, RGB calibration plan

## Live data on this site

- [/color/](/color/) — color grid pages, rounds, charts
- [/color/color_settings.json](/color/color_settings.json) — settings JSON
- [/color/color_settings.csv](/color/color_settings.csv) — settings CSV
- [/color/b4_measured.json](/color/b4_measured.json) — measured results
- [/color/rounds.json](/color/rounds.json) — round index
- [/tools/](/tools/) — tools index (includes color chart assets)

Related rule: [Polished stainless](materials/stainless-polished.md).

**v3:** one colour = one layer; multi-pass stacks are sub-layers. Full cut_settings shown in the browsers. Library/.clb sub-layer export is **unverified** until a LightBurn open-test.


## Source: `api.md`

# Colour plates JSON API (v3)

Single live colour database for `/color/`, `/colors/`, `/plates/`, `/tools/` and `/tech/`. Machine shown everywhere: **ComMarker B4 60W MOPA, 110 mm lens, LightBurn 1.7.08** (other charts only as “adapted from”).

## Public reads
- `GET /api/materials` — materials + all colours
- `GET /api/materials/{id}/colors` — one material (supports filter query params)
- `GET /api/colors` / `GET /api/colors/query` — unified list with filters:
  - `confidence=hank_verified,high` · `material=` / `materials=` · `status=` · `vivid=1|0`
  - `mode=fill,line,image` · `wobble=1|0` / `wobble_enable=` · `fill_grouping=1|0`
  - ranges: `power=10..40` · `speed=` · `freq=` · `pulse=` · `interval=` · `passes=`
  - `dot_width=` / `dot_width_mm=` · `line_width=` · `line_interval=`
  - `sort=confidence` or `power_pct:asc` / `dot-width` / `line-width` / `mode` …
  - `q=` text search · `plate=` · `group=` (client-side also)
- `GET /api/colors/{id}` — one colour (full `cut_settings` + `sublayers[]`)
- `GET /api/plates` · `GET /api/plates/P031`
- `GET /api/cite?q=Plate%2031,%20A8` — also `P5 A5`, `P031-A8` (includes `cut_settings` / `sublayers`)
- `GET /api/legend`
- `GET /api/library.clb?...` — LightBurn material library download (same filters as `/api/colors`). `Content-Disposition: attachment; filename="library.clb"`. **Sub-layer CutSetting siblings are UNVERIFIED** until Hank does one LightBurn open-test.

## Cut settings + sub-layers (v3)
- Every colour/cell has `cut_settings` (first sub-layer / primary) and `sublayers[]` with the full Cut Settings Editor field set (Fill / Line / Image). Unknown = null; defaulted fields listed in `settings_defaulted`.
- **One colour = one layer.** Multi-pass stacks are sub-layers inside that one layer (e.g. HD fill black = 1 entry with 16 sub-layers). UI shows Fill/Line/Image sections and sub-layer tabs; warns when sub-layers > 11.
- `lines_per_inch` and `min_tabs_per_shape` are DB/site only (no LightBurn XML element). Do not promise they round-trip.
- Library export: one `<Entry>` per colour, one sibling `<CutSetting>` per sub-layer. Serialization shape is a guess — **not verified** in LightBurn 1.7.08.

## Hank-only writes (accounts gate `laserview-admin` + user hank)
- `POST /api/colors/{id}/save` — body `{color: {...}}` full record (incl. `cut_settings` / `sublayers`); auto `confidence=hank_verified`; timestamped backup + audit log
- `POST /api/plates/P###/cells/A8/save` — `{cell:{...}}` full cell save
- `POST /api/plates/P###/save` — full plate object
- `POST /api/materials/save` — full materials.json
- Photo propose/confirm endpoints unchanged
- Logged-out writes return **401**

## Assets
- One photo: `/plates/P031/photo.jpg`
- Test files: `/plates/P010/<file>.lbrn2`
- Legend: `/color/LEGEND.md` · `/api/legend`
- Docs: `/docs/VPS_UPDATE.md` · `/docs/EXPORTER.md`
- `b4_measured.json` is **regenerated** from this DB (not a divergent cache)

## UI
- `/color/` and `/colors/` — identical unified browser (filters/sort/group in URL query; cut-settings panels + sub-layer tabs; library download buttons)
- `/plates/` — plate list + same browser; `/plates/P###/` — grid + photo + lbrn2
- `/tech/` · `/tools/` — same DB/API

## Filter UI (2026-10-16 follow-up)
Categorical query params accept comma lists (OR within a param, AND across params):
`confidence`, `material`/`materials`, `status`, `mode`, `plate`, `vivid` (`1`/`0`), `wobble`, `fill_grouping`.
Shared browsers use checkbox multi-select with Select all / Clear per group.


## Source: `tools.md`

# Tools / converters

- `dump_layers.py <folder>` writes `<name>_LAYERS.txt` for each `.lbrn2` in the folder.
- `recenter55.py` moves 63,63 projects to 55,55 (backups go in a `pre55/` folder; use `--dry` to audit).
- `to_ss245.py <file|folder>` makes 24.5 mm polished-stainless copies (`<name>_ss245`) mapped to `ss_color_palette.json` (verified: purple R1-0106, blue R1-0904, deep blue R1-0805, black lines; gold **UNTESTED**), strips the brass clean/polish layers, and takes `--map PATTERN=key` overrides. Pass `--hd-black` for the verified 14× R1-0106 HD fill black (slow; lean default otherwise).
- Washer no-hole method: remove the hole from the fill/strip/frame layers and add a centre motif in the same style.

- Colour plates API: public `GET /api/materials`, `/api/plates`, `/api/cite?q=`; Hank-only photo upload and cell edits — see [Colour plates API](api.md). UI at [/plates/](/plates/) and the material dropdown on [/color/](/color/).

- Unified colour browser: [/color/](/color/) and [/colors/](/colors/) (same DB). Filters in URL, e.g. `?confidence=hank_verified,high&sort=power_pct:asc`. Cite `Plate 31, A8` via `/api/cite`.
