← Commit history
README.md+25−1
@@ -11,7 +11,7 @@ verbs.  ```bash adom-wiki pkg install barrett-land/adom-desktop-altium-bridge   # the skill, in the container-adom-desktop bridge_install '{"manifestUrl":"https://wiki.adom.inc/download/barrett-land/adom-desktop-altium-bridge/0.0.41/altium-bridge-manifest.json"}'+adom-desktop bridge_install '{"manifestUrl":"https://wiki.adom.inc/download/barrett-land/adom-desktop-altium-bridge/0.0.42/altium-bridge-manifest.json"}' adom-desktop --ai-thread "<your thread>" altium_ping '{}' ``` @@ -26,6 +26,30 @@ adom-desktop --ai-thread "<your thread>" altium_ping '{}' | Edit | `altium_add_component` `altium_set_visibility` `altium_rename_component` `altium_rename_footprint` `altium_remove_component` | | Package | `altium_compile_intlib` `altium_extract_intlib` `altium_cleanup_libs` `altium_close_doc` | | Batch output | `altium_export_step` `altium_run_outjob` |+| Extension | `altium_install_extension` (installs the in-process .NET server) |++## Headless STEP export (via the extension)++Altium registers no parameterized processes, so from outside you only get parameterless,+dialog-driven commands. This package ships a small in-process .NET extension that fixes that:++```bash+adom-desktop --ai-thread "<thread>" altium_install_extension '{}'   # Altium must be CLOSED+# start Altium, then:+X2.exe -RAdomBridge:ExportStep(Req=C:\Users\Public\AdomAltium\exportstep_req.txt)+```++The request file carries `PcbDoc`, `Out`, and options — `Holes=All` for **real drilled geometry**+(mounting holes become actual holes, not pad artwork), `Copper=All` to bake 3D copper into the+STEP, `Models=Step|Extruded|Both`.++🔴 Altium's `-R` parser **splits on whitespace**, so a path with a space is truncated *and* the+leftover tokens are opened as files. Never put data on the command line — that is why parameters+go in a request file at a space-free path.++⚠️ Installing or updating the extension requires Altium **closed** (it holds the DLL open), and a+failed load takes Altium down at startup. Put `extension/REMOVE-AdomBridge.cmd` on the Desktop+first: it is a self-contained one-click rollback.  ## What it can't 
SKILL.md+120−2
@@ -12,7 +12,7 @@ forwards work into the running GUI as DelphiScript via `X2.EXE`. ## Install  ```bash-adom-desktop bridge_install '{"manifestUrl":"https://wiki.adom.inc/download/barrett-land/adom-desktop-altium-bridge/0.0.41/altium-bridge-manifest.json"}'+adom-desktop bridge_install '{"manifestUrl":"https://wiki.adom.inc/download/barrett-land/adom-desktop-altium-bridge/0.0.42/altium-bridge-manifest.json"}' adom-desktop --ai-thread "<your thread>" altium_ping '{}'   # -> {"altiumInstalled": true, "version": "..."} ``` @@ -94,6 +94,12 @@ adom-desktop --ai-thread "<thread>" altium_run_outjob '{ | **Gerber** (`.GTL` copper, `.GTO` silk, `.GTS` mask, `.GM1` outline) | ✅ yes | | **ExportSTEP** | ❌ no — `GenerateReport` no-ops; a human must click *Generate content* once | +> **For STEP, do not use an OutJob at all — use `AdomBridge:ExportStep`** (see the extension+> section below). It is fully headless, and exposes hole/copper options the OutJob route never had.++Also note an OutJob only generates if it is a **member of the project**; a stray `.OutJob` dropped+in the folder reports `Files Generated: 0`.+ The STEP exception is not a misconfiguration. It was verified with `ObjectKind=OutputBatch/OutputMedium/Document`, with and without `OutputMedium`, and with the OutJob already a member of a compiled project. Ask the user to click the button rather than@@ -109,7 +115,9 @@ rebuilding an OutJob that is already correct. - The real one, `PCB:Export`, is index-based (`Group=Model`) and opens a file dialog.  `run: true` now demands an explicit `proc` (a probe hatch only) and fails loudly when no file-appears. **To actually get a STEP, use an ExportSTEP OutJob plus one human click.**+appears. **To get a STEP, use `AdomBridge:ExportStep` from the extension** — headless, parameterized+and strictly better than the OutJob route. The OutJob-plus-click path remains as a fallback if the+extension is not installed.  ### The STEP has no copper and no silkscreen @@ -123,6 +131,116 @@ it alone is a bare green board. Rebuild both from Gerbers: Composite them into one RGBA overlay and pass it to `step2glb --silk-top` (which only takes effect with `--molecule`). The full recipe lives in the **altium-export-molecule** skill. +Alternatively, `AdomBridge:ExportStep` with `Copper=All` bakes real 3D copper into the STEP so no+overlay is needed — at a large size cost (1.9 MB → 57.7 MB on a mid-size board).++## The AdomBridge extension — parameterized, non-interactive verbs++Altium registers **no parameterized processes** for the things automation actually needs. From+outside the process you get parameterless, dialog-driven commands, and that single fact is why+STEP export, OutJob→PDF and KiCad import were all blocked. Code running **inside** Altium can call+the SDK directly, so this package ships a small .NET extension that registers processes which+take arguments.++### Install++```bash+# Altium MUST be closed first (see below).+adom-desktop --ai-thread "<thread>" altium_install_extension '{}'+# then start Altium — extensions are only read at startup+```++`altium_install_extension '{"remove": true}'` uninstalls. Both are idempotent, need no elevation+(the Extensions folder and `ExtensionsRegistry.xml` carry an inherited `Everyone: Modify` ACE), and+back up the registry with a timestamp before touching it.++⚠️ **Altium must be closed to install or update.** Once any AdomBridge process has run, Altium+holds `AdomBridge.dll` open and the copy fails with *"Access to the path is denied"*. The verb+detects this and says so rather than half-applying.++⚠️ **A failed extension load takes Altium down at startup**, not just the extension — the blast+radius is the whole application. `extension/REMOVE-AdomBridge.cmd` is a self-contained+double-click rollback; put it on the user's Desktop **before** installing so recovery never depends+on the agent being reachable.++### How dispatch works++```bash+"C:\Program Files\Altium\AD26\X2.exe" -RAdomBridge:<Process>(Key=Value|Key2=Value2)+```++Altium forwards this to the already-running instance and **loads the server lazily**, on first use+— so an absent load log right after startup is normal, not a failure.++🔴 **Altium's `-R` parser splits on WHITESPACE.** A path containing a space is truncated at the+first space *and* the remaining tokens are treated as files to open, at which point Altium tries to+start a second instance and Windows returns `ERROR_INVALID_STATE (0x8007139F)`. **Never put data on+the command line.** Write a request file at a space-free path and pass only its path.++### `AdomBridge:ExportStep` — headless STEP export++This replaces the OutJob-plus-human-click route entirely.++```bash+# 1. request file at a SPACE-FREE path; spaces are safe INSIDE it+cat > C:\Users\Public\AdomAltium\exportstep_req.txt <<'REQ'+PcbDoc=C:\...\SL1 Xilinx Spartan-IIE PQ208 Rev1.02.PcbDoc+Out=C:\...\board.step+Holes=All+PadHoles=true+Copper=None+Models=Step+REQ++# 2. dispatch+X2.exe -RAdomBridge:ExportStep(Req=C:\Users\Public\AdomAltium\exportstep_req.txt)++# 3. result lands in C:\Users\Public\AdomAltium\adombridge_exportstep.txt+#    (reports exists= and bytes= from the filesystem, not from the call)+```++| Key | Values | Default | Notes |+|---|---|---|---|+| `PcbDoc` | path | — | required |+| `Out` | path | — | required, `.step` |+| `Holes` | `All` `Selected` `None` | `All` | **real drilled geometry** |+| `PadHoles` | `true` `false` | `true` | mechanical + electrical + free pad holes |+| `Copper` | `None` `Only` `All` `Layer` | `None` | bakes copper in as 3D solids |+| `Models` | `Step` `Extruded` `Both` | `Step` | component body source |+| `Folded` | `true` `false` | `false` | flex/folded board |++**Holes matter.** Without them the board is a solid slab and mounting holes exist only as pad+artwork. Measured on SpiritLevel-SL1: 1,657,922 B / 3,599 meshes without → **1,874,312 B / 3,727+meshes with**, and the holes are visibly through the board.++**Copper is expensive.** `Copper=All` bakes every trace and pour as a solid: the same board goes+from 1.9 MB to **57.7 MB**. Use it when you want true 3D copper instead of a painted overlay;+otherwise leave it `None` and composite the pads from Gerbers.++The export opens the board with `ShowDocumentDontFocus` and resolves it via `GetPCBBoardByPath`, so+it neither steals the user's screen nor depends on which document happens to be focused.++### `AdomBridge:Ping` — connectivity++`-RAdomBridge:Ping(Msg=hello)` writes `adombridge_ping.txt`. Use it to prove the extension loaded+and that `-R` dispatch reaches it.++### Extending it++Source: `bridge-src/extension/` (prebuilt DLL) and the `adom-altium-extension` project.+Cross-built on Linux against the in-box .NET 8 Altium assemblies, because the design machine has no+.NET SDK. Rules learned the hard way:++- **Never let an exception escape `InvokePluginFactory`** — it is unhandled inside X2.EXE startup+  and kills the application. Wrap the whole body; return `null` to degrade to "extension absent".+- Do **not** set `EnableDynamicLoading`; it emits `.deps.json`/`.runtimeconfig.json` the assembly+  then requires. Altium loads managed servers into its own CoreCLR and ships neither file.+- The factory is COM-activated: keep `[ComVisible(true)]` and a **valid hex** `[Guid]`.+- Entry point is `CSharpPlugin.PluginFactory.InvokePluginFactory(IClient)`; the server derives from+  `DXP.ServerModule` and registers via the concrete `DXP.CommandLauncher.RegisterCommand`.++---+ ## Developing the bridge  Source lives in the page repo under `bridge-src/`. Three files each carry their own list of what
altium-bridge-manifest.json+3−3
@@ -1,3 +1,3 @@-{ "manifest_version": 1, "name": "altium", "version": "0.0.41",-  "url": "https://wiki.adom.inc/download/barrett-land/adom-desktop-altium-bridge/0.0.41/altium-bridge-v0.0.41.zip",-  "sha256": "ce614444afefcdffa56f4d03e57ff4fdd4bd13d2f8b59859477f2b192db9c92f", "size": 26776, "released_at": "2026-08-05T22:16:21Z" }+{ "manifest_version": 1, "name": "altium", "version": "0.0.42",+  "url": "https://wiki.adom.inc/download/barrett-land/adom-desktop-altium-bridge/0.0.42/altium-bridge-v0.0.42.zip",+  "sha256": "cba583cb0e56b776769b3f0c21812fc62b3d3e974a17cc223a1fe2d22036d7b2", "size": 37658, "released_at": "2026-08-05T23:40:39Z" }
altium-bridge-v0.0.42.zipadded
⋯ 1 unchanged line ⋯
bridge-src/BRIDGE_VERSION+1−1
@@ -1 +1 @@-0.0.41+0.0.42
bridge-src/__pycache__/check_wiring.cpython-312.pyc
⋯ 1 unchanged line ⋯
bridge-src/__pycache__/server.cpython-312.pyc
⋯ 1 unchanged line ⋯
bridge-src/bridge.json+3−2
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "altium",   "displayName": "Altium Bridge",-  "version": "0.0.41",+  "version": "0.0.42",   "description": "Drives Altium Designer from a container: build, clone and edit file-based symbol/footprint/Integrated libraries with LCSC/JLCPCB part numbers attached, and generate batch outputs (STEP, PDF, Gerber, BOM, CPL) from an OutJob. Pairs with the container-side altium-jlc orchestrator (adom-jlcpcb + chip-fetcher).",   "homepage": "https://wiki.adom.inc/adom/adom-desktop-altium-bridge",   "author": "Adom Inc.",@@ -47,7 +47,8 @@     "altium_copy_footprint",     "altium_script_state",     "altium_export_step",-    "altium_run_outjob"+    "altium_run_outjob",+    "altium_install_extension"   ],   "dependencies": {     "python": ">=3.8"
bridge-src/check_wiring.py+2−1
@@ -24,7 +24,8 @@ import sys from pathlib import Path  # Verbs the server answers itself, with no in-Altium counterpart to match against.-HOST_ONLY = {"altium_ping", "altium_detect", "altium_script_state"}+HOST_ONLY = {"altium_ping", "altium_detect", "altium_script_state",+             "altium_install_extension"}   def routed_verbs(server_py: Path) -> dict:
bridge-src/extension/AdomBridge/AdomBridge.dlladded
⋯ 1 unchanged line ⋯
bridge-src/extension/AdomBridge/AdomBridge.insadded+21
@@ -0,0 +1,21 @@+ClientInsFile 1.0++Server+    EditorName        = 'AdomBridge'+    EditorExePath     = 'AdomBridge.DLL'+    EditorDescription = 'Adom Bridge - parameterized processes for container automation'+    Version           = 'Version 0.2.0'+    Date              = '05-Aug-2026'+    HelpAboutInfo     = 'Adom Inc. in-process automation bridge.'+    Copyright         = 'Copyright Adom Inc. 2026'+End++Command+    Name = 'Ping'+    LongSummary = 'AdomBridge connectivity test - writes adombridge_ping.txt'+End++Command+    Name = 'ExportStep'+    LongSummary = 'Export a PcbDoc 3D model to STEP. PcbDoc=<path>|Out=<path>'+End
bridge-src/extension/AdomBridge/AdomBridge.rcsadded+15
@@ -0,0 +1,15 @@+PL PLAdomBridge_Ping+        Command='AdomBridge:Ping'+        Caption='Adom Ping'+        Image=''+        Params=''+        Description='AdomBridge connectivity test'+End++PL PLAdomBridge_ExportStep+        Command='AdomBridge:ExportStep'+        Caption='Adom Export STEP'+        Image=''+        Params=''+        Description='Export a PcbDoc 3D model to STEP'+End
bridge-src/extension/AdomBridge/Help/ServerDlls.txtadded+1
@@ -0,0 +1 @@+AdomBridge=AdomBridge\ No newline at end of file
bridge-src/extension/Install-AdomBridge.ps1added+100
@@ -0,0 +1,100 @@+# Install-AdomBridge.ps1 — hand-install the AdomBridge extension.+#+# Altium ships no silent extension-install CLI (AltiumInstaller.exe has no /silent-style switch,+# and no .rcs registers an install process), but the Extensions folder and ExtensionsRegistry.xml+# both carry an inherited "Everyone: Modify" ACE, so writing the files directly IS the supported+# shape. This is what a working third-party extension's Deploy.ps1 does too.+#+# Does NOT restart Altium — killing a live Altium risks unsaved schematics. Restart is the+# caller's decision, made explicitly.+#+#   powershell -ExecutionPolicy Bypass -File Install-AdomBridge.ps1 -Source <dir> [-Remove]++[CmdletBinding()]+param(+    [string] $Source = "$PSScriptRoot\AdomBridge",+    [switch] $Remove+)+$ErrorActionPreference = 'Stop'++$adRoot = Get-ChildItem 'C:\ProgramData\Altium' -Directory |+          Where-Object { $_.Name -like 'Altium Designer*' } | Select-Object -First 1+if (-not $adRoot) { throw 'No "Altium Designer {GUID}" folder under C:\ProgramData\Altium' }++$extRoot = Join-Path $adRoot.FullName 'Extensions'+$target  = Join-Path $extRoot 'AdomBridge'+$reg     = Join-Path $extRoot 'ExtensionsRegistry.xml'+$guid    = 'CDFE1901-218C-5A6A-BEF9-E5BE7083B9FC'++Write-Output "extensions root : $extRoot"+Write-Output "registry        : $reg"++# --- always back the registry up before touching it -------------------------------------+$backup = "$reg.bak-" + (Get-Date -Format 'yyyyMMdd-HHmmss')+Copy-Item -LiteralPath $reg -Destination $backup -Force+Write-Output "registry backup : $backup"++$xml = [xml](Get-Content -LiteralPath $reg -Raw)+$existing = $xml.SelectNodes('//Item') | Where-Object { $_.GetAttribute('HRID') -eq 'AdomBridge' }+foreach ($n in $existing) { [void]$n.ParentNode.RemoveChild($n) }   # idempotent re-install++if ($Remove) {+    $xml.Save($reg)+    if (Test-Path $target) { Remove-Item -LiteralPath $target -Recurse -Force }+    Write-Output 'REMOVED (restart Altium to unload)'+    exit 0+}++# --- files ------------------------------------------------------------------------------+if (Test-Path $target) { Remove-Item -LiteralPath $target -Recurse -Force }+Copy-Item -LiteralPath $Source -Destination $target -Recurse -Force+Write-Output "installed files : $target"+Get-ChildItem $target -Recurse -File | ForEach-Object { Write-Output ('   ' + $_.FullName.Substring($target.Length + 1)) }++# --- registry node ----------------------------------------------------------------------+# Field set mirrors the shipped entries; anything Altium fills in itself is left empty.+$item = $xml.CreateElement('Item')+$item.SetAttribute('HRID', 'AdomBridge')+$item.SetAttribute('Guid', $guid)+function Add-Child([string]$name, [string]$text) {+    $e = $xml.CreateElement($name); $e.InnerText = $text; [void]$item.AppendChild($e)+}+Add-Child 'Path'             $target+Add-Child 'Status'           '0'+Add-Child 'VaultGuid'        ''+Add-Child 'CreatedBy'        'Adom Inc.'+Add-Child 'CategoryGuid'     ''+Add-Child 'CategoryName'     ''+Add-Child 'ReadMe'           ''+Add-Child 'Help'             ''+Add-Child 'Requirements'     ''+Add-Child 'Title'            'Adom Bridge'+Add-Child 'ShortDescription' 'Parameterized in-process automation for container-driven Altium.'+Add-Child 'LongDescription'  'Registers processes that accept arguments, so a container can drive Altium without the wizard-and-click surface Altium exposes externally.'+Add-Child 'SmallImage'       ''+Add-Child 'LargeImage'       ''+Add-Child 'Version'          '0.1.0.0'+Add-Child 'VersionGuid'      ([guid]::NewGuid().ToString().ToUpper())+$oleNow = [string]([datetime]::Now.ToOADate())+Add-Child 'ReleasedDate'     $oleNow+Add-Child 'ReleaseNotes'     ''+Add-Child 'DateInstalled'    $oleNow++# Shipped entries all carry this block; absent it, the client may treat the entry as malformed.+$pv = $xml.CreateElement('PlatformVersions')+foreach ($pair in @(@('DXP','1.0.16.43'), @('EDP','10.0.16.43'), @('MaxDXP','0.0.0.0'), @('MaxEDP','0.0.0.0'))) {+    $e = $xml.CreateElement($pair[0]); $e.SetAttribute('BuildNumber', $pair[1]); [void]$pv.AppendChild($e)+}+[void]$item.AppendChild($pv)+[void]$xml.DocumentElement.AppendChild($item)++# AltiumInstaller carries a "…it is opened by some process" string, so tolerate a transient lock.+for ($i = 0; $i -lt 5; $i++) {+    try { $xml.Save($reg); break }+    catch { if ($i -eq 4) { throw }; Start-Sleep -Seconds 2 }+}++$check = [xml](Get-Content -LiteralPath $reg -Raw)+$n = ($check.SelectNodes('//Item') | Where-Object { $_.GetAttribute('HRID') -eq 'AdomBridge' }).Count+Write-Output "registry items  : $(($check.SelectNodes('//Item')).Count) total, AdomBridge nodes = $n"+Write-Output 'INSTALLED — Altium must be restarted before the server is loaded.'
bridge-src/extension/REMOVE-AdomBridge.cmdadded+38
@@ -0,0 +1,38 @@+@echo off+REM ============================================================================+REM  EMERGENCY ROLLBACK - double-click this if Altium will not start.+REM+REM  Deletes the AdomBridge extension folder and its ExtensionsRegistry.xml entry,+REM  returning Altium to exactly how it was before the extension was installed.+REM  Needs no admin rights and no network. Safe to run twice.+REM+REM  After it finishes, start Altium normally.+REM ============================================================================+setlocal+echo.+echo   Removing the AdomBridge Altium extension...+echo.++powershell -NoProfile -ExecutionPolicy Bypass -Command ^+  "$ErrorActionPreference='Stop';" ^+  "$root = Get-ChildItem 'C:\ProgramData\Altium' -Directory | Where-Object { $_.Name -like 'Altium Designer*' } | Select-Object -First 1;" ^+  "if (-not $root) { Write-Host '  No Altium Designer folder found - nothing to do.'; exit 0 };" ^+  "$ext = Join-Path $root.FullName 'Extensions';" ^+  "$dir = Join-Path $ext 'AdomBridge';" ^+  "$reg = Join-Path $ext 'ExtensionsRegistry.xml';" ^+  "if (Test-Path $dir) { Remove-Item -LiteralPath $dir -Recurse -Force; Write-Host '  removed folder :' $dir } else { Write-Host '  folder already gone' };" ^+  "if (Test-Path $reg) {" ^+  "  Copy-Item -LiteralPath $reg -Destination ($reg + '.bak-remove-' + (Get-Date -Format 'yyyyMMdd-HHmmss')) -Force;" ^+  "  $x = [xml](Get-Content -LiteralPath $reg -Raw);" ^+  "  $n = @($x.SelectNodes('//Item') | Where-Object { $_.GetAttribute('HRID') -eq 'AdomBridge' });" ^+  "  foreach ($i in $n) { [void]$i.ParentNode.RemoveChild($i) };" ^+  "  for ($k=0; $k -lt 5; $k++) { try { $x.Save($reg); break } catch { Start-Sleep -Seconds 2 } };" ^+  "  Write-Host '  removed registry entries :' $n.Count;" ^+  "  $c = [xml](Get-Content -LiteralPath $reg -Raw);" ^+  "  Write-Host '  registry now has' @($c.SelectNodes('//Item')).Count 'items'" ^+  "} else { Write-Host '  no ExtensionsRegistry.xml found' }"++echo.+echo   Done. Start Altium normally.+echo.+pause
bridge-src/server.py+47
@@ -257,6 +257,52 @@ def handle_cleanup_libs(args: dict) -> dict:     return addin_call("cleanup_libs", {"match": match}, timeout=args.get("timeout", 60))  +def _extension_dir() -> Path:+    return Path(__file__).parent / "extension"+++def handle_install_extension(args: dict) -> dict:+    """Install (or with remove=true, uninstall) the in-process AdomBridge Altium extension.++    The extension is what makes parameterized, non-interactive verbs possible at all -- from+    outside the process Altium only exposes parameterless dialog-driven processes. Installing+    is pure file-copy plus one node in ExtensionsRegistry.xml; both targets carry an inherited+    Everyone:Modify ACE, so no elevation is needed.++    ALTIUM MUST BE CLOSED. Once any AdomBridge process has run, Altium holds AdomBridge.dll+    open and the copy fails with 'Access to the path is denied'. And Altium only loads+    extensions at startup, so a restart is required afterwards either way.+    """+    src = _extension_dir()+    installer = src / "Install-AdomBridge.ps1"+    if not installer.exists():+        return {"ok": False, "error": f"installer missing at {installer}"}++    import subprocess+    cmd = ["powershell", "-NoProfile", "-ExecutionPolicy", "Bypass",+           "-File", str(installer), "-Source", str(src / "AdomBridge")]+    if args.get("remove"):+        cmd.append("-Remove")++    try:+        p = subprocess.run(cmd, capture_output=True, text=True, timeout=args.get("timeout", 180))+    except Exception as e:+        return {"ok": False, "error": f"installer failed to run: {e}"}++    out, err = (p.stdout or "").strip(), (p.stderr or "").strip()+    ok = p.returncode == 0 and "denied" not in err.lower()+    res = {"ok": ok, "removed": bool(args.get("remove")), "output": out}+    if err:+        res["stderr"] = err[:800]+    if "denied" in err.lower():+        res["error"] = "AdomBridge.dll is locked - close Altium and retry."+        res["_hint"] = ("Altium holds the extension DLL open once any AdomBridge process has run. "+                        "Close Altium, re-run this verb, then start Altium again.")+    else:+        res["_hint"] = "Restart Altium to load the extension; it is only read at startup."+    return res++ def handle_script_state(args: dict) -> dict:     """Which in-Altium script is live vs. the one this bridge package ships. @@ -375,6 +421,7 @@ COMMAND_HANDLERS = {     "altium_ping": handle_ping,     "altium_detect": handle_detect,     "altium_script_state": handle_script_state,+    "altium_install_extension": handle_install_extension,     "altium_export_step": handle_export_step,     "altium_run_outjob": handle_run_outjob,     "altium_compile_intlib": handle_compile_intlib,
package.json+8−7
@@ -1,8 +1,8 @@ {   "slug": "adom-desktop-altium-bridge",-  "version": "0.0.41",+  "version": "0.0.42",   "type": "app",-  "description": "Adom Desktop bridge for Altium Designer \u2014 build and edit file-based symbol/footprint/Integrated libraries with LCSC/JLCPCB part numbers attached, and generate batch outputs (STEP, PDF, Gerber, BOM, CPL) from an OutJob, by driving Altium via DelphiScript.",+  "description": "Adom Desktop bridge for Altium Designer: file-based symbol/footprint/IntLib authoring with LCSC/JLCPCB part numbers, Gerber/BOM/CPL batch output, and an in-process .NET extension that adds parameterized headless verbs including STEP export with hole and copper options.",   "tags": [     "app",     "adom-desktop",@@ -21,13 +21,14 @@     "path": "docs/hero.png"   },   "discovery_triggers": [-    "add a part to my altium library",     "drive altium from claude",     "altium bridge",-    "export step from altium",-    "run an altium outjob",-    "build an altium footprint",-    "altium symbol library"+    "export step from altium headless",+    "add a part to my altium library",+    "altium extension",+    "install altium extension",+    "altium step export",+    "run an altium outjob"   ],   "discovery_pitch": "Use when the user wants Claude to author or edit Altium libraries, or to generate STEP/PDF/Gerber/BOM/CPL from an Altium board on their Windows machine.",   "sample_prompts": [
page.json+10−8
@@ -1,8 +1,8 @@ {   "slug": "adom-desktop-altium-bridge",-  "version": "0.0.41",+  "version": "0.0.42",   "type": "app",-  "description": "Adom Desktop bridge for Altium Designer \u2014 build and edit file-based symbol/footprint/Integrated libraries with LCSC/JLCPCB part numbers attached, and generate batch outputs (STEP, PDF, Gerber, BOM, CPL) from an OutJob, by driving Altium via DelphiScript.",+  "description": "Adom Desktop bridge for Altium Designer: file-based symbol/footprint/IntLib authoring with LCSC/JLCPCB part numbers, Gerber/BOM/CPL batch output, and an in-process .NET extension that adds parameterized headless verbs including STEP export with hole and copper options.",   "tags": [     "app",     "adom-desktop",@@ -18,6 +18,7 @@   },   "needs_sudo": false,   "hero": {+    "type": "image",     "path": "docs/hero.png"   },   "author": {@@ -25,13 +26,14 @@     "email": "[email protected]"   },   "discovery_triggers": [-    "add a part to my altium library",     "drive altium from claude",     "altium bridge",-    "export step from altium",-    "run an altium outjob",-    "build an altium footprint",-    "altium symbol library"+    "export step from altium headless",+    "add a part to my altium library",+    "altium extension",+    "install altium extension",+    "altium step export",+    "run an altium outjob"   ],   "discovery_pitch": "Use when the user wants Claude to author or edit Altium libraries, or to generate STEP/PDF/Gerber/BOM/CPL from an Altium board on their Windows machine.",   "sample_prompts": [@@ -48,4 +50,4 @@       "prompt": "Is the Altium bridge connected and what version is it?"     }   ]-}+}\ No newline at end of file