Worked example: AMS1117, end to end

The build that produced adom/ams-ams1117 and adom/umw-ams1117, in order, including the two places it went wrong first.

0. What made this a good test case

AMS1117 is a jellybean 1 A LDO whose part number is second-sourced. It exercises every hard part of the skill: a datasheet family (six voltages, three packages), a manufacturer collision, a footprint whose tab is an electrical net, and two existing per-variant pages that should never have been created.

1. Get the datasheet, then read it before anything else

The datasheet is the page boundary (SKILL.md section 1), so it comes first.

adom-desktop --ai-thread "<thread>" desktop_list_files \
  '{"path":"C:\\Users\\<user>\\Downloads","glob":"*1117*"}'
adom-desktop --ai-thread "<thread>" pull_file \
  '{"filePaths":["C:\\Users\\<user>\\Downloads\\ds1117.pdf"],"destDir":"/tmp"}'

Then Read the PDF with the pages parameter and take the ordering table, the electrical characteristics tables and the package drawings.

A stalled Chrome download shows up as Unconfirmed NNNNNN.crdownload with no extension. It is a complete file. Check the magic bytes rather than assuming the download failed.

2. Decide the boundary

The AMS ordering table lists 1.5 / 1.8 / 2.5 / 2.85 / 3.3 / 5.0 V across SOT-223, TO-252 and 8-lead SOIC. That is one page.

Two existing pages, adom/ams1117-3-3 and adom/ams1117-1-2, were per-variant splits of that same family. They should not have existed.

Then the second datasheet arrived: UMW / Youtai Semiconductor, same part number, carrying 1.2 V and not 2.85 V, SOT-89 instead of SO-8, 18 V input maximum instead of 15 V, 2.1 to 2.5 A current limit instead of 0.9 to 1.5 A, and thermal shutdown at 150 C instead of 165 C.

The first attempt merged both onto one page with a comparison table and an "available from" column per variant. That was rejected, correctly: a merged page needs a vendor caveat on every number, which is what gets misread. Two datasheets, two pages.

3. CAD, pulled not authored

All three AMS packages and all three UMW packages exist in KiCad 10's official library on the user's machine, with matching STEP models.

adom-desktop --ai-thread "<t>" desktop_list_files \
  '{"path":"C:\\Program Files\\KiCad\\10.0\\share\\kicad\\footprints\\Package_TO_SOT_SMD.pretty","glob":"SOT-223*"}'

adom-desktop --ai-thread "<t>" pull_file '{"filePaths":[
 "C:\\Program Files\\KiCad\\10.0\\share\\kicad\\footprints\\Package_TO_SOT_SMD.pretty\\SOT-223-3_TabPin2.kicad_mod",
 "C:\\Program Files\\KiCad\\10.0\\share\\kicad\\3dmodels\\Package_TO_SOT_SMD.3dshapes\\SOT-223.step"
],"destDir":"/tmp"}'

SOT-223-3_TabPin2 and not plain SOT-223, because the AMS1117 tab is VOUT, internally bonded to pin 2. The existing adom/ams1117-3-3 page shipped a SnapEDA pattern with the tab on pad 4 as its own net, which leaves the heat path floating.

Rename both the node and the Value property:

t = t.replace('(footprint "SOT-223-3_TabPin2"', '(footprint "AMS1117_SOT-223"', 1)
t = re.sub(r'\(property "Value" "[^"]*"', '(property "Value" "AMS1117_SOT-223"', t, count=1)
t = re.sub(r'\(model "[^"]*"', '(model "${KIPRJMOD}/ams1117-sot223.step"', t)

Then:

step2glb convert ams1117-sot223.step --out ams1117-sot223.glb

cat > sym.json <<'JSON'
{"symbolName":"AMS1117","manufacturer":"Advanced Monolithic Systems","package":"SOT-223",
 "description":"AMS1117 1 A low-dropout linear regulator","designatorPrefix":"U",
 "datasheetUrl":"http://www.advanced-monolithic.com/pdf/ds1117.pdf","footprint":"AMS1117_SOT-223",
 "pins":[{"number":"3","name":"VIN","type":"power_in","side":"left"},
         {"number":"2","name":"VOUT","type":"power_out","side":"right"},
         {"number":"1","name":"GND/ADJ","type":"power_in","side":"bottom"}]}
JSON
adom-symbol create --file sym.json --out ./sym
adom-lbr import-kicad --sym ams1117.kicad_sym --fp ams1117-sot223.kicad_mod --mpn AMS1117 --out ams1117.adom-lbr.json

4. Viewers, with the fab-layer workaround

adom-symbol embed --file ams1117.kicad_sym --out viewer-symbol.html

for f in sot223 to252 so8; do
  adom-footprint embed --file ams1117-$f.kicad_mod --out /tmp/raw-$f.html
  python3 scripts/inject_layers.py /tmp/raw-$f.html ams1117-$f.kicad_mod fp-$f.html
done
python3 scripts/build_switcher.py . AMS viewer-footprints.html

Without inject_layers.py the viewer shows floating pads with no body outline, because adom-footprint 1.0.20 emits the fab, silk and courtyard groups empty (adom/adom-footprint#2). The viewer's own LAYER_DEFS already defines all three and groupHasGeo() shows a row as soon as a group holds geometry, so filling the groups is the entire fix.

5. Hero

three.js plus puppeteer, GLB rendered as a 3/4 product shot inside a floating window, composited into a billboard on the brand tokens. Two gotchas:

  • puppeteer needs --allow-file-access-from-files because the three.js importmap uses file:// URLs, and the script must run where node_modules resolves (symlink it into the scratchpad).
  • The SOT-223 GLB needed root.rotation.z = Math.PI to face its three leads forward instead of the tab. That is an in-plane spin applied before the Z-up rotation.x = -Math.PI/2, under Euler XYZ order.

6. Publish both layers

adom-wiki pkg publish --org adom --public --include-media
adom-wiki repo push adom/ams-ams1117 -m "AMS1117 (Advanced Monolithic Systems) component page" \
  --files page.json README.md readme.html ams1117.kicad_sym ams1117-so8.kicad_sym \
  ams1117-sot223.kicad_mod ams1117-to252.kicad_mod ams1117-so8.kicad_mod \
  ams1117-sot223.step ams1117-to252.step ams1117-so8.step \
  ams1117-sot223.glb ams1117-to252.glb ams1117-so8.glb ams1117.adom-lbr.json \
  viewer-symbol.html viewer-footprints.html docs/ams1117-datasheet-ams.pdf \
  screenshots/hero.png screenshots/datasheet-cover.png

The registry lowercases slugs, so publishing AMS-AMS1117 yields ams-ams1117. Write the cross-links lowercase from the start.

7. Verify live, not locally

curl -s -o /dev/null -w "%{http_code}\n" \
  https://wiki.adom.inc/api/v1/pages/adom/ams-ams1117/files/readme.html

Then screenshot. The first live capture of the footprint switcher came back blank and looked like a CSP problem; it was puppeteer painting before the large srcdoc iframes had rendered. Wait about 5 s after networkidle2. Diff live against local by character count, because µ and Ω make byte counts differ on identical files.

8. Deprecate what this replaced

The combined adom/ams1117 page became wrong once the split happened. A banner in the readme was not enough: it renders far below the fold and the header looked live. What made it visibly deprecated (SKILL.md section 8):

# title -> "[DEPRECATED] 1 A Low-Dropout Regulator - AMS1117 → ams-ams1117 / umw-ams1117"
# tags  -> ["deprecated","alias","ams-ams1117","umw-ams1117", ...]
# brief -> leads with "DEPRECATED. Use ..."
# hero  -> replaced with a struck-through signpost image
adom-wiki repo push adom/ams1117 --files page.json -m "..."
adom-wiki pkg publish --org adom
for v in 1.0.0 1.1.0 1.2.0 1.2.1 1.2.2; do
  adom-wiki pkg deprecate "adom/ams1117@$v" "Split by manufacturer: use adom/ams-ams1117 or adom/umw-ams1117."
done

json.dumps escapes the arrow to \u2192 unless you pass ensure_ascii=False.

9. Chase the dependents

Repointing is a registry-layer change, so it needs a pkg publish on each dependent, not a repo push. Issues were filed on every page that depended on the old slugs rather than editing other people's boards:

  • adom/ams1117-3-3 and adom/ams1117-1-2: deprecate, pointing at the vendor page that matches the silicon. 1.2 V is UMW-only, so that one is unambiguous.
  • adom/ams1117-3v3-molecule and adom/large-automotive-eth-switch-molecule: repoint the dependency, and check the tab pad is on the VOUT net given the wrong footprint they inherited.

What was found along the way

Two real defects in pages that already existed, both now written into issues:

  1. adom/ams1117-3-3 ships a footprint with the tab on pad 4 as its own net. The tab is VOUT (pin 2).
  2. adom/ams1117-1-2 ships a footprint that is entirely on back layers (B.Cu / B.Mask / B.Paste / B.SilkS / B.Fab / B.CrtYd) with no front geometry at all. Anything placed from it lands bottom-side.

Both are the kind of thing that only surfaces when someone rebuilds a page against the datasheet. That is the argument for this skill existing.