@hybridlabor-api/aos 4.4.2-beta.3 → 4.4.2-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -47,6 +47,7 @@ const AGENTS = [
47
47
  ];
48
48
 
49
49
  const MODULE_DIRS = ['memB', 'bdb-synapse', 'bdb-os-remote', 'bdb-dev-creator-extension',
50
+ 'bdb-hardware-pcb',
50
51
  'bdb-dev-tool-installer',
51
52
  'bdb-agent-orchestrator', // AO
52
53
  'bdb-os-agent-workspace', // AO's archived predecessor, if still lying around
@@ -181,6 +181,16 @@
181
181
  | `triage` | Move issues and external PRs through a state machine of triage roles, categorise, verify, and write agent-ready briefs. |
182
182
  | `typescript-pro` | Master TypeScript with advanced types, generics, and strict type safety. Handles complex type systems, decorators, and enterprise-grade patterns. |
183
183
 
184
+ #### 🔩 Engineering & Hardware
185
+ | Skill Name | Description |
186
+ |------------|-------------|
187
+ | `godmode-hardware-pcb` | Architectural authority for electrical schematics, PCB layout, KiCad projects, and OpenSCAD enclosures — trace geometry, impedance, stackup, and DFM/DRC/ERC sign-off. Use when designing or reviewing physical hardware before it goes to fabrication. |
188
+ | `code-first-hardware-design` | Programmatic schematic capture, circuit synthesis (SKiDL, text netlists, S-expressions), and parametric 3D CAD enclosure co-design (OpenSCAD/BOSL2). Use when generating circuits in code, exporting netlists, scripting KiCad schematics, or designing 3D enclosures. |
189
+ | `pcb-constraint-definition` | Translates high-level hardware requirements into formal engineering constraints, layer stackup calculations, netclasses, and custom DRC rules for KiCad. Use when defining board constraints, stackup, impedance matching, power budgeting, or netclasses. |
190
+ | `pcb-layout-routing-automation` | Floorplanning, component placement rules, high-speed differential pair routing, return path continuity, thermal via arrays, and keepout enforcement for KiCad PCB layouts. Use when placing footprints, routing traces, creating ground planes, or managing thermal/RF keepouts. |
191
+ | `pcb-validation-dfm-signoff` | Automated DRC/ERC verification, SI/PI screening, fab house DFM/DFA compliance, and production release sign-off for KiCad projects. Use when running final design rule checks, auditing manufacturing limits, generating Gerbers/BOM/CPL, or issuing DFM sign-off reports. |
192
+ | `schematic-datasheet-analysis` | Electrical rule auditing, datasheet grounding, pinout validation, power tree tracing, and negative evidence analysis for KiCad schematics. Use when analyzing schematics, auditing pinmux/logic levels, checking component ratings, or validating datasheets. |
193
+
184
194
  #### 📦 Other Utilities
185
195
  | Skill Name | Description |
186
196
  |------------|-------------|
package/installer.js CHANGED
@@ -694,6 +694,32 @@ function flushSessionManifest() {
694
694
  if (_sessionManifest) saveInstallManifest(_sessionManifest);
695
695
  }
696
696
 
697
+ // skills/global_legacy/ has not existed in the shipped payload for a long
698
+ // time -- the three `if (dir === 'global_legacy')` copy branches elsewhere in
699
+ // this file have been dead code ever since, since that name never appears in
700
+ // a fresh fs.readdirSync(skillsBase). Nothing populates a fresh
701
+ // targetLegacyDir any more, but nothing ever removed an OLD one either: a
702
+ // real Windows install this session still had 126 stale legacy skill copies
703
+ // sitting in .codex/skills/legacy, indexed alongside the current top-level
704
+ // copies of the same skills by the harness's own skill picker -- the
705
+ // "duplicate skills" a live test reported. Since the source category is
706
+ // permanently gone, an existing legacy dir is unconditionally obsolete, not
707
+ // merely unmanaged: retire it instead of recreating an eternally-empty
708
+ // placeholder for it.
709
+ function retireObsoleteLegacyDir(targetLegacyDir) {
710
+ if (!targetLegacyDir || !fs.existsSync(targetLegacyDir)) return;
711
+ if (fs.existsSync(path.join(srcDir, 'skills', 'global_legacy'))) {
712
+ fs.mkdirSync(targetLegacyDir, { recursive: true });
713
+ return;
714
+ }
715
+ try {
716
+ fs.rmSync(targetLegacyDir, { recursive: true, force: true });
717
+ log.step(`Removed retired legacy skill copies at ${targetLegacyDir} (global_legacy has not shipped in a long time).`);
718
+ } catch (e) {
719
+ logDebug(e, 'retire legacy dir');
720
+ }
721
+ }
722
+
697
723
  function resolveMcpsArg(availableMcps) {
698
724
  const requested = mcpsArg.split(',').map(s => s.trim()).filter(Boolean);
699
725
  const wantsNone = requested.some(r => ['none', 'core', 'core-only'].includes(r.toLowerCase()));
@@ -785,7 +811,10 @@ function detectPlatforms() {
785
811
  },
786
812
  {
787
813
  key: 'codex', name: 'ChatGPT Codex CLI', path: path.join(homeDir, '.codex'),
788
- evidence: () => hasExecutable('codex'),
814
+ // Codex ships two ways: the standalone CLI binary, and embedded in
815
+ // the ChatGPT desktop app. A machine can have either without the
816
+ // other (e.g. ChatGPT desktop only, codex never put on PATH).
817
+ evidence: () => hasExecutable('codex') || anyExists(appBundle('ChatGPT')),
789
818
  },
790
819
  {
791
820
  key: 'claudecode', name: 'Claude Code CLI', path: path.join(homeDir, '.claude'),
@@ -900,6 +929,7 @@ function detectInstallState() {
900
929
  // The archived predecessor is deliberately NOT detected: a copy of it
901
930
  // should be removed, not carried forward into another install.
902
931
  { id: 'creator', dir: path.join(basePath, 'bdb-dev-creator-extension') },
932
+ { id: 'hardware', dir: path.join(basePath, 'bdb-hardware-pcb') },
903
933
  { id: 'installer', dir: path.join(basePath, 'bdb-dev-tool-installer') }
904
934
  ];
905
935
 
@@ -910,13 +940,23 @@ function detectInstallState() {
910
940
  }
911
941
 
912
942
  const currentVersion = pkg.version || '3.9.6';
913
- const updateAvailable = isInstalled && (localVersion !== currentVersion);
943
+ // Was a bare !== -- any version string difference counted as "update
944
+ // available", downgrade included. A real Windows session ran `@latest`
945
+ // (resolving to the actual latest stable, 4.4.1) against a machine
946
+ // already on 4.4.2-beta.3 and the installer silently treated dropping two
947
+ // versions the same as a normal update -- no distinction, no warning.
948
+ // isNewerVersion() already exists and already handles prerelease
949
+ // ordering correctly; this just uses it in both directions instead of
950
+ // only for the npm-registry freshness check it was written for.
951
+ const versionChanged = isInstalled && localVersion !== currentVersion;
952
+ const isDowngrade = versionChanged && isNewerVersion(currentVersion, localVersion);
953
+ const updateAvailable = versionChanged && !isDowngrade;
914
954
 
915
955
  // Extend: also load the file-level install manifest so the caller can
916
956
  // seed manifest-aware writes during this same session.
917
957
  const installManifest = loadInstallManifest();
918
958
 
919
- return { isInstalled, localVersion, currentVersion, updateAvailable, installedModules, manifest, installManifest };
959
+ return { isInstalled, localVersion, currentVersion, updateAvailable, isDowngrade, installedModules, manifest, installManifest };
920
960
  }
921
961
 
922
962
  function saveManifest(data = {}) {
@@ -1134,13 +1174,20 @@ function syncSkillsToGlobalHarnesses(excludeSkills = []) {
1134
1174
  // the very directories detectPlatforms() then read back as proof the
1135
1175
  // harness existed. ~/.agents is ours and always written.
1136
1176
  const detectedKeys = new Set(detectPlatforms().map((d) => d.key));
1177
+ // No `|| fs.existsSync(d.dir)` fallback here on purpose: that fallback
1178
+ // used to mean a directory AOS itself planted in a past run (before a
1179
+ // harness was ever really detected) kept being "detected" forever,
1180
+ // regardless of what detectPlatforms() found this run -- the exact
1181
+ // circularity the block comment above warns about, just one layer down.
1182
+ // A harness that stops being detected now simply stops receiving skill
1183
+ // updates instead of perpetuating a false positive.
1137
1184
  const extraSkillDestinations = [
1138
1185
  { dir: path.join(homeDir, '.agents', 'skills'), key: null },
1139
1186
  { dir: path.join(homeDir, '.claude', 'skills'), key: 'claudecode' },
1140
1187
  { dir: path.join(homeDir, '.codex', 'skills'), key: 'codex' },
1141
1188
  { dir: path.join(homeDir, '.cursor', 'skills'), key: 'cursor' },
1142
1189
  { dir: path.join(homeDir, '.roo', 'skills'), key: 'vscode' },
1143
- ].filter((d) => d.key === null || detectedKeys.has(d.key) || fs.existsSync(d.dir));
1190
+ ].filter((d) => d.key === null || detectedKeys.has(d.key));
1144
1191
 
1145
1192
  for (const { dir: dest } of extraSkillDestinations) {
1146
1193
  try {
@@ -1208,15 +1255,42 @@ function maskApiKey(key) {
1208
1255
  return key.substring(0, 4) + '...' + key.substring(key.length - 4);
1209
1256
  }
1210
1257
 
1211
- async function promptCredentials(referenceMcpDir) {
1212
- if (isAutoYes) return { gemini: "", github: "", openwikiProvider: "google", openwikiModel: "", openwikiBaseUrl: "", keyEnvName: 'GEMINI_API_KEY' };
1258
+ // Provider -> its own API key env var name. Used both to find a previously
1259
+ // configured non-Google provider's key (loadExistingEnv only special-cased
1260
+ // Gemini/GitHub, so a Groq/Grok/NVIDIA/OpenAI/OpenRouter setup was invisible
1261
+ // to "keep existing" and silently looked unconfigured) and to build the
1262
+ // isAutoYes default without re-deriving the same mapping twice.
1263
+ const PROVIDER_KEY_ENV_NAMES = {
1264
+ google: 'GEMINI_API_KEY', groq: 'GROQ_API_KEY', grok: 'XAI_API_KEY',
1265
+ nvidia: 'NVIDIA_API_KEY', openrouter: 'OPENROUTER_API_KEY',
1266
+ openai: 'OPENAI_API_KEY', ollama: null, custom: 'OPENWIKI_API_KEY',
1267
+ };
1213
1268
 
1269
+ async function promptCredentials(referenceMcpDir) {
1214
1270
  const existingEnv = loadExistingEnv(referenceMcpDir);
1215
- const existingGemini = existingEnv['GEMINI_API_KEY'] || existingEnv['GOOGLE_API_KEY'] || existingEnv['OPENWIKI_API_KEY'] || '';
1216
1271
  const existingGithub = existingEnv['GITHUB_PERSONAL_ACCESS_TOKEN'] || existingEnv['GITHUB_TOKEN'] || '';
1217
1272
  const existingProvider = existingEnv['OPENWIKI_PROVIDER'] || 'google';
1218
1273
  const existingModel = existingEnv['OPENWIKI_MODEL'] || '';
1219
1274
  const existingBaseUrl = existingEnv['OPENWIKI_BASE_URL'] || '';
1275
+ const existingKeyEnvName = PROVIDER_KEY_ENV_NAMES[existingProvider] || 'OPENWIKI_API_KEY';
1276
+ // Gemini/Google/OpenWiki-generic keys are also accepted as a fallback so
1277
+ // an old config written before OPENWIKI_PROVIDER existed still resolves.
1278
+ const existingGemini = existingEnv[existingKeyEnvName] || existingEnv['GEMINI_API_KEY'] || existingEnv['GOOGLE_API_KEY'] || existingEnv['OPENWIKI_API_KEY'] || '';
1279
+
1280
+ if (isAutoYes) {
1281
+ // A non-interactive run (npx -y, or an --auto submodule install) must
1282
+ // never silently discard a provider already configured on this
1283
+ // machine -- this used to hard-reset to an empty Google/Gemini
1284
+ // default on every unattended re-run, wiping a previously-chosen
1285
+ // NVIDIA/Nemotron (or any other) provider and key each time.
1286
+ if (existingGemini || existingProvider === 'ollama') {
1287
+ return { gemini: existingGemini, github: existingGithub, openwikiProvider: existingProvider, openwikiModel: existingModel, openwikiBaseUrl: existingBaseUrl, keyEnvName: existingKeyEnvName };
1288
+ }
1289
+ // Nothing configured yet on this machine: default to NVIDIA NIM /
1290
+ // Nemotron. Google was only ever a placeholder default, never the
1291
+ // intended house default.
1292
+ return { gemini: "", github: existingGithub, openwikiProvider: "nvidia", openwikiModel: "nvidia/llama-3.1-nemotron-70b-instruct", openwikiBaseUrl: "https://integrate.api.nvidia.com/v1", keyEnvName: 'NVIDIA_API_KEY' };
1293
+ }
1220
1294
 
1221
1295
  const hasKeys = Boolean(existingGemini || existingGithub);
1222
1296
 
@@ -1243,7 +1317,7 @@ async function promptCredentials(referenceMcpDir) {
1243
1317
  openwikiProvider: existingProvider,
1244
1318
  openwikiModel: existingModel,
1245
1319
  openwikiBaseUrl: existingBaseUrl,
1246
- keyEnvName: existingProvider === 'google' ? 'GEMINI_API_KEY' : 'OPENWIKI_API_KEY'
1320
+ keyEnvName: existingKeyEnvName
1247
1321
  };
1248
1322
  }
1249
1323
  }
@@ -1928,6 +2002,25 @@ async function installCreatorExtension() {
1928
2002
  }
1929
2003
  }
1930
2004
 
2005
+ async function installHardwarePcb() {
2006
+ const hwDir = path.join(moduleBasePath(), 'bdb-hardware-pcb');
2007
+ if (!downloadOrUpdateModule('@hybridlabor-api/bdb-hardware-pcb', hwDir, 'BDB Hardware & PCB (KiCad + OpenSCAD)')) {
2008
+ log.warn('Skipping Hardware & PCB setup: the module could not be downloaded.');
2009
+ return;
2010
+ }
2011
+ if (DRY_RUN) {
2012
+ log.step('[dry-run] would run BDB Hardware & PCB setup');
2013
+ return;
2014
+ }
2015
+ const installerScript = path.join(hwDir, 'installer.js');
2016
+ if (fs.existsSync(installerScript)) {
2017
+ const setupResult = spawnSync('node', [installerScript, '--auto'], { stdio: 'inherit', cwd: hwDir });
2018
+ if (setupResult.status !== 0) {
2019
+ log.warn(`Hardware & PCB setup note: exit code ${setupResult.status}`);
2020
+ }
2021
+ }
2022
+ }
2023
+
1931
2024
  async function installOSRemoteGateway() {
1932
2025
  const remoteDir = path.join(moduleBasePath(), 'bdb-os-remote');
1933
2026
  if (!downloadOrUpdateModule('@hybridlabor-api/bdb-os-remote', remoteDir, 'BDB OS Remote Gateway')) {
@@ -2074,9 +2167,10 @@ function verifyEcosystemInstallation() {
2074
2167
  { name: '3. heimdall-token-saver', pkg: '@hybridlabor-api/heimdall-token-saver', paths: [path.join(moduleBasePath(), 'heimdall-token-saver'), path.join(srcDir, 'vendor', 'token-saver')] },
2075
2168
  { name: '4. AO Agent Orchestrator', pkg: '@hybridlabor-api/bdb-agent-orchestrator', paths: [path.join(moduleBasePath(), 'bdb-agent-orchestrator')] },
2076
2169
  { name: '5. bdb-dev-creator-extension', pkg: '@hybridlabor-api/bdb-dev-creator-extension', paths: [path.join(moduleBasePath(), 'bdb-dev-creator-extension')] },
2077
- { name: '6. bdb-os-remote', pkg: '@hybridlabor-api/bdb-os-remote', paths: [path.join(moduleBasePath(), 'bdb-os-remote')] },
2078
- { name: '7. bdb-dev-tool-installer', pkg: '@hybridlabor-api/bdb-dev-tool-installer', paths: [path.join(moduleBasePath(), 'bdb-dev-tool-installer')] },
2079
- { name: '8. aos (bdb agent os)', pkg: '@hybridlabor-api/aos', paths: [srcDir] }
2170
+ { name: '6. bdb-hardware-pcb', pkg: '@hybridlabor-api/bdb-hardware-pcb', paths: [path.join(moduleBasePath(), 'bdb-hardware-pcb')] },
2171
+ { name: '7. bdb-os-remote', pkg: '@hybridlabor-api/bdb-os-remote', paths: [path.join(moduleBasePath(), 'bdb-os-remote')] },
2172
+ { name: '8. bdb-dev-tool-installer', pkg: '@hybridlabor-api/bdb-dev-tool-installer', paths: [path.join(moduleBasePath(), 'bdb-dev-tool-installer')] },
2173
+ { name: '9. aos (bdb agent os)', pkg: '@hybridlabor-api/aos', paths: [srcDir] }
2080
2174
  ];
2081
2175
 
2082
2176
  for (const mod of modules) {
@@ -3179,6 +3273,7 @@ async function promptOptionalModules(installedModules) {
3179
3273
  ? [{ id: 'ao', name: 'AO Agent Orchestrator (Session telemetry & WebUI)', fn: installOSAgentWorkspace }]
3180
3274
  : []),
3181
3275
  { id: 'creator', name: 'BDB Creator Extension (Generative 3D, Video & ComfyUI)', fn: installCreatorExtension },
3276
+ { id: 'hardware', name: 'BDB Hardware & PCB (KiCad + OpenSCAD Electrical/PCB Design)', fn: installHardwarePcb },
3182
3277
  { id: 'installer', name: 'BDB Dev Tool Installer (Interactive Hub & CLI Launcher)', fn: installDevToolInstaller }
3183
3278
  ];
3184
3279
 
@@ -3520,7 +3615,7 @@ async function runQuickUpdate(installState) {
3520
3615
 
3521
3616
  fs.mkdirSync(backupDir, { recursive: true });
3522
3617
  fs.mkdirSync(paths.targetSkillDir, { recursive: true });
3523
- fs.mkdirSync(paths.targetLegacyDir, { recursive: true });
3618
+ retireObsoleteLegacyDir(paths.targetLegacyDir);
3524
3619
  fs.mkdirSync(paths.targetWorkspaceDir, { recursive: true });
3525
3620
 
3526
3621
  // Initialize manifest for this update session.
@@ -3593,6 +3688,7 @@ async function runQuickUpdate(installState) {
3593
3688
  // 'ao' intentionally skipped here even for
3594
3689
  // existing installs -- see promptOptionalModules() for why.
3595
3690
  else if (subId === 'creator') await installCreatorExtension();
3691
+ else if (subId === 'hardware') await installHardwarePcb();
3596
3692
  else if (subId === 'installer') await installDevToolInstaller();
3597
3693
  }
3598
3694
 
@@ -3945,7 +4041,7 @@ async function main() {
3945
4041
 
3946
4042
  installStep(`create the skill target directories (${t.value})`, () => {
3947
4043
  fs.mkdirSync(t.targetSkillDir, { recursive: true });
3948
- fs.mkdirSync(t.targetLegacyDir, { recursive: true });
4044
+ retireObsoleteLegacyDir(t.targetLegacyDir);
3949
4045
  fs.mkdirSync(t.targetWorkspaceDir, { recursive: true });
3950
4046
  }, 'The skill copies below will most likely be skipped as well.');
3951
4047
 
package/lib/startup-ui.js CHANGED
@@ -122,7 +122,9 @@ function buildTelemetryCard({ installState, detections, daemonStatus = [] }) {
122
122
  // 3. Installation State
123
123
  if (installState) {
124
124
  if (installState.isInstalled) {
125
- const versionStatus = installState.updateAvailable
125
+ const versionStatus = installState.isDowngrade
126
+ ? `${BRAND.amber}⚠${BRAND.reset} ${BRAND.white}v${installState.localVersion}${BRAND.reset} installed ${BRAND.amber}(this payload is v${installState.currentVersion} — older, not an update)${BRAND.reset}`
127
+ : installState.updateAvailable
126
128
  ? `${BRAND.amber}v${installState.localVersion}${BRAND.reset} ➔ ${BRAND.emerald}${BRAND.bold}v${installState.currentVersion}${BRAND.reset} ${BRAND.amber}(Update Available)${BRAND.reset}`
127
129
  : `${BRAND.emerald}✔${BRAND.reset} ${BRAND.white}v${installState.currentVersion}${BRAND.reset} ${BRAND.dim}(Current & Up-to-date)${BRAND.reset}`;
128
130
  lines.push(`${G} ${BRAND.lila}└─${BRAND.reset} ${BRAND.dim}Kernel State:${BRAND.reset} ${versionStatus}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hybridlabor-api/aos",
3
- "version": "4.4.2-beta.3",
3
+ "version": "4.4.2-beta.5",
4
4
  "description": "AOS — A Curated AI AGENT OS. Optimized agent skills and add-ons like memB, OpenWiki, Heimdall Token Saver, and Godmode architectures.",
5
5
  "main": "installer.js",
6
6
  "bin": {
@@ -13,7 +13,7 @@ const SKILLS = join(REPO, 'skills');
13
13
 
14
14
  const CATEGORIES = new Set([
15
15
  'design-ui-ux', 'engineering-method', 'media-eventtech',
16
- 'bdb-core', 'saas-ops', 'library',
16
+ 'bdb-core', 'saas-ops', 'library', 'engineering-hardware',
17
17
  ]);
18
18
  const REQUIRED = ['name', 'description', 'category'];
19
19
 
@@ -0,0 +1,102 @@
1
+ ---
2
+ name: godmode-hardware-pcb
3
+ description: "Use when designing electrical schematics, PCB layouts, KiCad projects, or OpenSCAD enclosures — trace geometry, impedance, stackup, DFM/DRC/ERC sign-off, and hardware-software co-design boundaries."
4
+ category: engineering-hardware
5
+ ---
6
+
7
+ # ⚡ BDB Hardware & PCB Godmode
8
+
9
+ This skill is the architectural authority for **Electrical Schematics, PCB Layout, Physical Constraints, and Manufacturing Sign-Off** in the AOS hardware engineering pipeline. It defines how agents must derive physical parameters from first principles, validate designs against IPC standards, and gate release to fabrication — without compromising on measurable, machine-checkable evidence.
10
+
11
+ ---
12
+
13
+ ## 1. Role & Architectural Boundaries
14
+
15
+ * **Physical Design Authority:** Governs schematic capture, board layout, layer stackup, netclass definition, controlled-impedance routing, and DFM/DFA sign-off across KiCad-driven projects. Also governs parametric enclosure and mechanical co-design via OpenSCAD.
16
+ * **Peer Integration:** Operates alongside `godmode-engineering` (firmware and software running on the board) and `godmode-eventtech` (live show-control hardware in the field) — this skill owns the board and enclosure itself, not the code that runs on it or the show that uses it. A request that touches firmware register maps or a live show's signal budget hands off to those peers instead of being re-derived here.
17
+ * **No Informal Constraints:** A schematic or layout may never proceed on default trace widths, unconstrained nets, or "it looked fine in the 3D viewer." Every physical parameter traces back to a formula or a standard, not a guess.
18
+
19
+ ---
20
+
21
+ ## 2. Mathematical and Physical Foundations
22
+
23
+ All trace geometry and thermal boundaries are derived from first principles and IPC standards, never estimated by eye:
24
+
25
+ * **Trace Current Capacity (IPC-2152):** $I = k \cdot \Delta T^{0.44} \cdot A^{0.725}$, with $k = 0.048$ for external (convective) traces and $k = 0.024$ for internal (conductive-only) traces. A $2.5\text{A}$ DC rail at $\Delta T = 10^\circ\text{C}$ on $1\text{ oz}$ external copper needs $\approx 0.79\text{mm}$ trace width — not a rounded-up guess.
26
+ * **Controlled Impedance (IPC-2141):** Single-ended microstrip $Z_0 = \frac{87}{\sqrt{\varepsilon_r + 1.41}} \ln\left(\frac{5.98h}{0.8w+t}\right)$; edge-coupled differential $Z_{diff} \approx 2Z_0\left(1 - 0.48e^{-0.96 s/h}\right)$. USB is a $90\Omega$ differential target, Ethernet/PCIe is $100\Omega$ — these are not interchangeable, and getting the pair spacing wrong by a fraction of $h$ misses the target by more than manufacturing tolerance forgives.
27
+ * **DC IR Drop:** $R_{trace} = \rho \cdot L / (w \cdot t)$, $V_{drop} = I_{peak} \cdot R_{trace}$. On a $+3.3\text{V}$ rail, $V_{drop}$ must stay $\le 0.10\text{V}$ ($3\%$); if it doesn't, widen the trace or move the net to a copper flood — don't just note the number and move on.
28
+ * **Crosstalk (the 3W rule):** center-to-center separation $D \ge 3w$ for parallel traces longer than $15\text{mm}$ keeps mutual coupling below a $70\%$ reduction threshold. This is the default spacing assumption for any signal or clock line, not an optional refinement.
29
+
30
+ ---
31
+
32
+ ## 3. Headless Validation — the Unforgiving Gate
33
+
34
+ **No board may be released to fabrication on visual inspection or LLM self-attestation.** This is not a style preference; it's the same lesson this whole ecosystem has paid for repeatedly elsewhere: a clean-looking run is not evidence, a real exit code is.
35
+
36
+ * **ERC:** `kicad-cli sch erc --exit-code-violations -o reports/erc_report.txt project.kicad_sch` — exit 0 means zero errors and zero unhandled warnings, not "looks connected."
37
+ * **DRC:** `kicad-cli pcb drc --exit-code-violations --format json -o reports/drc_report.json board.kicad_pcb` — must show zero unrouted nets, zero clearance violations, zero broken annular rings, zero thermal spoke disconnections.
38
+ * **DFM/DFA:** benchmark the layout against the target fab house's real capabilities (e.g. JLCPCB standard, PCBWay 4-layer minimum trace/space/via), not a generic "should be fine" assumption.
39
+ * A non-zero exit code from any of the above is an immediate gate blockage — the pipeline halts, it does not continue with a caveat noted for later.
40
+
41
+ ---
42
+
43
+ ## 4. Dedicated MCP Tool Validation Requirement
44
+
45
+ Before issuing schematic edits, layout changes, or fabrication exports, the agent MUST validate the required MCP servers are actually reachable — not assume they are because a config file lists them:
46
+
47
+ 1. **KiCad MCP:** validate the kicad-mcp-server responds over stdio (`tools/list` returns its full tool set — schematic editing, PCB layout, ERC/DRC execution, Gerber/BOM/CPL export) before issuing any node or netlist command.
48
+ 2. **OpenSCAD MCP:** validate the openscad-mcp-server responds before requesting parametric model generation, modification, or STL/3MF export for enclosure co-design.
49
+ 3. **Version awareness:** a stale or absent `kicad-cli` (KiCad 8+) or `openscad` binary on the host changes what's actually possible — check for it and say so plainly, rather than emitting commands that will fail downstream with no clear cause.
50
+
51
+ ---
52
+
53
+ ## 5. Hardware/Software Co-Design Boundary
54
+
55
+ * PCB and enclosure design decisions here must stay coordinated with, but not encroach on, the firmware/software skills that consume the resulting pinout and register map — a GPIO reassignment on the board is a breaking change to firmware that already assumed the old pin, and must be flagged as such, not silently absorbed.
56
+ * Mechanical (OpenSCAD) and electrical (KiCad) constraints are two halves of the same physical object: a connector placement that satisfies routing but collides with the enclosure wall is not a valid design, even if ERC/DRC both pass.
57
+
58
+ ---
59
+
60
+ ## Universal Agent Harness Integration
61
+
62
+ This Godmode rulebook is universally available across the BDB ecosystem, installed alongside the `@hybridlabor-api/bdb-hardware-pcb` module (KiCad + OpenSCAD MCP servers, 5 companion skills under the `engineering-hardware` category):
63
+ * **Claude Code / CLI Agents:** loaded during electrical, PCB, and enclosure design sessions.
64
+ * **Peer skills:** `code-first-hardware-design`, `pcb-constraint-definition`, `pcb-layout-routing-automation`, `pcb-validation-dfm-signoff`, `schematic-datasheet-analysis`.
65
+
66
+ ## Overview
67
+ This skill acts as the architectural authority for electrical and PCB design, enforcing IPC-standard physical constraints, headless validation gates, and hardware/software co-design boundaries.
68
+
69
+ ## When to Use
70
+ - **Trigger:** The user is designing or modifying a schematic, PCB layout, layer stackup, netclass, or an OpenSCAD enclosure meant to house the board.
71
+ - **Exclude:** Do not use for firmware/register-level software running on the board (hand off to `godmode-engineering`), or for live show-control signal routing in the field (hand off to `godmode-eventtech`).
72
+
73
+ ## Core Process
74
+ 1. Derive every trace width, impedance target, and clearance from the formulas above or a cited IPC standard — never from a rounded-up guess.
75
+ 2. Validate KiCad and OpenSCAD MCP servers are actually responsive before issuing edits.
76
+ 3. Run headless ERC and DRC with `--exit-code-violations`; treat any non-zero exit as a hard stop.
77
+ 4. Benchmark the layout against the real target fab house's DFM limits before calling a design release-ready.
78
+ 5. Cross-check the enclosure (OpenSCAD) against the board outline and connector placements (KiCad) before sign-off.
79
+
80
+ ## Common Rationalizations
81
+
82
+ | Rationalization | Reality |
83
+ |---|---|
84
+ | "0.25mm default trace width is fine for a power rail." | IPC-2152 current-capacity math, not the CAD tool's default, sets minimum trace width — a 2.5A rail needs ~0.79mm at 1oz copper, not the default. |
85
+ | "The 3D viewer looks correct, so the board is done." | A visual check is not ERC/DRC. Only a headless run with `--exit-code-violations` and a real exit code is evidence. |
86
+ | "USB and Ethernet differential pairs can use the same spacing." | USB targets 90Ω differential, Ethernet/PCIe targets 100Ω — same formula, different required spacing for the same dielectric height. |
87
+ | "The GPIO can be reassigned in layout; firmware can just adapt." | A pin reassignment is a breaking change to any firmware that already assumed the old pinout — it must be flagged to the software side, not silently absorbed. |
88
+
89
+ ## Red Flags
90
+
91
+ - Proceeding to layout with unconstrained nets or no defined netclasses.
92
+ - Treating a clean-looking 3D render as equivalent to a passing ERC/DRC exit code.
93
+ - Skipping DFM benchmarking against the actual target fab house's capabilities.
94
+ - Changing a pinout or connector placement without flagging the firmware or enclosure impact.
95
+
96
+ ## Verification
97
+
98
+ - [ ] Every load-bearing trace width/impedance/clearance traces back to a formula or IPC standard, not a default or a guess.
99
+ - [ ] ERC and DRC were run headless with `--exit-code-violations`, and the actual exit code — not a description of the run — was checked.
100
+ - [ ] KiCad and OpenSCAD MCP tool availability was validated before issuing edits.
101
+ - [ ] DFM limits were checked against the real target fab house, not a generic assumption.
102
+ - [ ] Any pinout/connector change was cross-checked against firmware assumptions and enclosure geometry.
@@ -84,6 +84,7 @@ If the user's intent matches one of these, jump to the corresponding section:
84
84
  * **"I'm managing the BDB SaaS multi-cloud fleet"** ➔ [BDB Ecosystem & SaaS Ops](#bdb-ecosystem--saas-ops)
85
85
  * **"I need Three.js, 3D, or motion work"** ➔ [Media & EventTech](#media--eventtech)
86
86
  * **"I need live event tech, TouchDesigner, or Resolume help"** ➔ [Media & EventTech](#media--eventtech)
87
+ * **"I need PCB layout, schematic capture, or electrical/hardware design"** ➔ [Electrical & Hardware Design](#electrical--hardware-design)
87
88
 
88
89
  ---
89
90
 
@@ -304,6 +305,23 @@ Resolve and Premiere are interchangeable at this level: pick whichever is actual
304
305
 
305
306
  ---
306
307
 
308
+ ## 🔩 Electrical & Hardware Design
309
+
310
+ Use these for schematic capture, PCB layout, and physical hardware design (KiCad, OpenSCAD).
311
+
312
+ * **Top Picks:** `godmode-hardware-pcb`, `code-first-hardware-design`, `pcb-constraint-definition`
313
+
314
+ * **Architectural authority**: `godmode-hardware-pcb` — enforces IPC-standard trace/impedance/stackup math and the headless ERC/DRC/DFM sign-off gate across the skills below; load it before starting schematic or layout work.
315
+ * **Circuit synthesis & enclosures**: `code-first-hardware-design` — programmatic schematic capture (SKiDL, netlists, S-expressions) and parametric 3D CAD enclosure co-design (OpenSCAD/BOSL2).
316
+ * **Constraints & stackup**: `pcb-constraint-definition` — translates hardware requirements into layer stackup, netclasses, impedance matching, and custom DRC rules before layout starts.
317
+ * **Layout & routing**: `pcb-layout-routing-automation` — floorplanning, component placement, high-speed differential pair routing, thermal via arrays, and keepout enforcement.
318
+ * **Validation & sign-off**: `pcb-validation-dfm-signoff` — automated DRC/ERC, SI/PI screening, fab house DFM/DFA compliance, and production release sign-off (Gerbers/BOM/CPL).
319
+ * **Schematic & datasheet auditing**: `schematic-datasheet-analysis` — electrical rule auditing, datasheet grounding, pinout validation, and power tree tracing.
320
+
321
+ These ship in the separate `@hybridlabor-api/bdb-hardware-pcb` power-up module (KiCad + OpenSCAD MCP servers), not in this base skills package — install it as an optional AOS module when hardware work comes up.
322
+
323
+ ---
324
+
307
325
  ## 🛡️ Overlap: The Supreme Godmodes
308
326
 
309
327
  When do you use a `godmode-*` skill versus a narrower skill?