name: zbeam-chart-spec description: "Generates charts: block for a Z-Beam material page. Trigger: add chart, process window chart, chart spec for [slug]."
Z-Beam Chart Spec
Manual-only skill — not called by any automated pipeline or other skill. Trigger: "add a chart to [slug]" or "generate process window chart for [material]". Not scheduled. No callers. Runs only when Todd explicitly requests a chart.
Generates a charts: block for a material page YAML and maintains the shared
data/charts/process-windows.json comparison dataset used by the chart component.
Pipeline position: content-writer / page-updater → YOU → content-validator
Implementation: all Python functions live in references/chart-functions.py.
Run the full skill for a single slug:
cd /path/to/z-beam
python3 skills/charts/zbeam-chart-spec/references/chart-functions.py run [slug]
Only one chart type is justified by the data: the Process Window Chart.
Why only one? 60 of 74 material pages have valid process window data (ablationThreshold < laserDamageThreshold). Machine settings are not material-specific (78% of pages recommend the same 100 W setting; only 4 distinct scan speeds exist). Absorptivity is present on only 9/74 pages. A chart that is not grounded in material-specific data misleads rather than informs.
What the Process Window Chart shows
The x-axis is fluence in J/cm². Each bar is a material in the same subcategory.
The bar starts at ablationThreshold and ends at laserDamageThreshold.
The current page's material is highlighted. Materials are sorted narrowest window
at top → widest at bottom.
Viewer insight: "How forgiving is this material compared to others like it?" A contractor sees immediately that cast iron (0.7 J/cm² window) requires tighter parameter control than steel (3.0 J/cm²). This is the single most operational piece of information on a material page.
The chart is rendered by app/components/charts/ProcessWindowChart.tsx using
Recharts. See references/ProcessWindowChart.tsx for the component spec.
Step 0 — Data quality check
python3 skills/charts/zbeam-chart-spec/references/chart-functions.py check [slug]
Returns JSON: {valid, reason?, ablation?, damage?, window?, unit?}
If valid: false, stop. Report the specific reason. Do not write a charts: block.
For data entry errors (ablation >= damage): the most common cause is field reversal —
the ablation value was entered into laserDamageThreshold and vice versa. The lower
number is almost always the ablation threshold.
Step 1a — Operating point
The operating point is machineSettings.fields.energyDensity.value — renders as a
dashed vertical reference line showing where the machine runs relative to the safe window.
If machineSettings.fields.energyDensity is absent, omit operatingPoint — the chart
renders correctly without it.
Out-of-window warning: if operatingPoint ≤ ablation or ≥ damage, run() logs a
warning but does not block. Machine settings may be calibrated for a different contaminant.
Step 1b — Subcategory comparison dataset
All materials in the same subcategory with valid process windows (abl < dmg). Sorted narrowest window first.
Minimum comparison set: fewer than 2 peers → skip the chart. A single-bar chart
communicates nothing the data table doesn't already show. Write chartSkipped: true
with reason: 'insufficient subcategory peers' in the section stub.
Step 2 — Comparative caption
The caption must do three things:
- State the current material's window width explicitly
- Name at least one peer for contrast (narrowest or widest in subcategory)
- State a practical consequence (tight parameter control / more tolerance)
Examples:
- Cast iron: "Cast iron's 0.7 J/cm² window is the narrowest among ferrous metals — four times tighter than steel's 3.0 J/cm². A fluence increase that leaves steel unmarked can trigger graphite pullout on gray iron."
- Copper: "Copper's 0.23 J/cm² window is the tightest in the non-ferrous group — verify fluence calibration on representative samples before production runs."
- Silicon carbide: "Silicon carbide's 22.3 J/cm² window is the widest in the carbide group, offering substantial tolerance for parameter variation compared to tungsten carbide (9.5 J/cm²)."
Caption logic is implemented in references/chart-functions.py → run().
Step 3 — Update shared data file
references/chart-functions.py → run() calls update_shared_dataset() automatically.
To rebuild without touching page YAML (e.g. to pre-populate before component is built):
python3 skills/charts/zbeam-chart-spec/references/chart-functions.py dataset
data/charts/process-windows.json is the skill's internal working file only — NOT
a runtime dependency. All chart data the component needs is in page.charts[].
Step 4 — Two-level chart schema
page.charts[] — canonical data block. Contains all chart data: entries,
operatingPoint, SEO copy, AI citation copy, image path, JSON-LD fields. Read by
the renderer and JSON-LD pipeline.
body.laserInteraction.chart — slim stub only: type, generated, subcategory,
subcategoryLabel. Acts as a placement marker. Contains NO entries, NO caption,
NO operatingPoint.
Output schema
page:
title: ...
charts:
- id: fluence-window
kind: processWindow
name: "Cast iron ferrous fluence process window (Cast Iron, Iron, Steel)"
description: "AI citation copy — names both domains, includes specific measurement"
caption: "Cast iron's 0.7 J/cm² window is the narrowest among ferrous metals ..."
keywords:
- cast iron laser cleaning fluence window
about:
- Cast iron laser cleaning
image: /images/charts/cast-iron-laser-cleaning-fluence-window.png
imageWidth: 1200
imageHeight: 630
renderMode: both
sectionRef: body.laserInteraction.chart
unit: J/cm²
operatingPoint: 1.5 # omit if machineSettings.energyDensity absent
dateModified: "YYYY-MM-DD"
entries:
- slug: cast-iron-laser-cleaning
name: Cast Iron
ablation: 1.5
damage: 2.2
window: 0.7
isCurrent: true
body:
laserInteraction:
fields: ...
chart: # stub only — data lives in page.charts[]
type: processWindow
generated: "YYYY-MM-DD"
subcategory: ferrous
subcategoryLabel: Ferrous Metals
isCurrent is set by the script. name comes from the page's top-level name field —
never displayName (which appends "Laser Cleaning").
Batch mode
To rebuild data/charts/process-windows.json without modifying any page YAML:
python3 skills/charts/zbeam-chart-spec/references/chart-functions.py dataset
Validator integration
The absence of a charts: block is CONDITIONAL PASS — non-blocking.
Add this to skills/quality/zbeam-content-validator/references/dim6-structural-checks.md:
# chart: block inside body.laserInteraction (material pages) — absence = CONDITIONAL PASS
if content_type == 'material':
chart = ((page.get('body', {}) or {}).get('laserInteraction', {}) or {}).get('chart') or {}
if not chart:
issues.append('WARN Dim6: body.laserInteraction.chart absent — run zbeam-chart-spec')
elif chart.get('chartSkipped'):
pass # skipped for a documented reason — no warning
elif not chart.get('caption'):
issues.append('WARN Dim6: body.laserInteraction.chart.caption missing')
elif not chart.get('entries'):
issues.append('WARN Dim6: body.laserInteraction.chart.entries missing — re-run zbeam-chart-spec')
What this skill never does
- Does not fabricate absorptivity, thermal conductivity, or machine settings charts
- Does not generate a chart when ablation >= damage — those are data errors
- Does not produce multi-axis radar charts — visual complexity without viewer value
- Does not produce machine parameter charts — settings are not material-specific enough
- Does not override existing captions — if a
charts:block already exists with a caption, onlygenerated:date anddataSource:path are updated