@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.
- package/bin/aos-uninstall.mjs +1 -0
- package/docs/skills_table.md +10 -0
- package/installer.js +109 -13
- package/lib/startup-ui.js +3 -1
- package/package.json +1 -1
- package/scripts/validate-skills.mjs +1 -1
- package/skills/basic/godmode-hardware-pcb/SKILL.md +102 -0
- package/skills/global_config/ask-tim/SKILL.md +18 -0
package/bin/aos-uninstall.mjs
CHANGED
|
@@ -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
|
package/docs/skills_table.md
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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)
|
|
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
|
-
|
|
1212
|
-
|
|
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:
|
|
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-
|
|
2078
|
-
{ name: '7. bdb-
|
|
2079
|
-
{ name: '8.
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
+
"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?
|