← back to Agent Cabinet
Initial Cabinet scaffold: agent-architect + 6 VPs + Mermaid viewer on :9766
34a04722318974516e8690d5ddf6ed590bc46bb6 · 2026-05-06 11:25:14 -0700 · Steve
Files touched
A .gitignoreA cabinet.yamlA server.js
Diff
commit 34a04722318974516e8690d5ddf6ed590bc46bb6
Author: Steve <steve@designerwallcoverings.com>
Date: Wed May 6 11:25:14 2026 -0700
Initial Cabinet scaffold: agent-architect + 6 VPs + Mermaid viewer on :9766
---
.gitignore | 5 ++
cabinet.yaml | 216 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
server.js | 154 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 375 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b38eead
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+node_modules/
+.env*
+*.log
+.DS_Store
+tmp/
diff --git a/cabinet.yaml b/cabinet.yaml
new file mode 100644
index 0000000..41eebf4
--- /dev/null
+++ b/cabinet.yaml
@@ -0,0 +1,216 @@
+# THE CABINET — Steve's executive agent hierarchy.
+# Source of truth for the org chart. agent-architect reads/writes this file
+# and regenerates VP subagents + the mindmap viewer when it changes.
+#
+# Convention:
+# Steve (President) → VP (subagent) → Director (subagent OR named skill bundle) → Skills (leaves).
+#
+# Goal: as patterns emerge, Directors get absorbed into VPs and skills get retired.
+# Fewer agents, broader triggers, cleaner routing.
+
+president:
+ name: Steve
+ role: Chief Executive
+ email: steve@designerwallcoverings.com
+ reports_to: null
+
+cabinet:
+ - vp: vp-operations
+ domain: Infrastructure, monitoring, secrets, domains, DNS, watchdogs
+ triggers:
+ - infra | infrastructure | devops | server | uptime | crashed
+ - watchdog | pm2 | launchd | cron | scheduler
+ - secret | token | api key | rotate
+ - domain | dns | ssl | mx | spf | dkim | dmarc | cloudflare | godaddy
+ directors:
+ - skill: secrets
+ owns: [add token, rotate token, audit secrets, fan out env]
+ - skill: domain-setup
+ owns: [register, configure DNS, SSL, email auth]
+ - skill: domain-name-agent
+ owns: [domain inventory, NS swap, WHOIS]
+ - skill: cloudflare-manager
+ owns: [zone DNS, proxy toggle]
+ - skill: open-firewalls
+ owns: [Mac2 + Kamatera firewall]
+ - skill: process-hawk
+ owns: [auto-restart stuck pm2 processes]
+ - subagent: pm2-crash-watcher
+ - subagent: deployment-engineer
+ - subagent: devops-engineer
+ - subagent: domain-name-agent
+ - subagent: onboard-domain-agent
+ - subagent: secrets-manager
+
+ - vp: vp-dw-commerce
+ domain: Designer Wallcoverings catalog, vendor scrapers, Shopify, storefronts, marketing
+ triggers:
+ - shopify | dw_unified | metafield | sku | variant | catalog
+ - vendor | scrape | crawl | enrich
+ - storefront | dw site | philipperomano | flockedwallpaper | grasscloth
+ - marketing | seo | mailer | drops | instagram | tiktok
+ directors:
+ - skill: dw-site-build
+ owns: [universal DW storefront playbook]
+ - skill: dw-shopify-theme-optimizer
+ owns: [Liquid perf, image opts, Core Web Vitals]
+ - skill: dw-marketing-copy
+ owns: [titles, body, SEO, descriptions]
+ - skill: dw-seo-optimizer
+ owns: [meta + structured data]
+ - skill: dw-purchasing-vendor
+ owns: [vendor emails, POs, supplier pricing]
+ - skill: dw-sku-analyst
+ owns: [SKU normalization, dedup audits — like NCW + PR]
+ - skill: dw-legal-compliance
+ owns: [vendor contracts, settlement compliance]
+ - skill: room-setting-generator
+ owns: [photorealistic room renders]
+ - skill: commercial-room-setting-generator
+ owns: [contract / hospitality renders]
+ - skill: shopify-vendor-bulk-updater
+ owns: [bulk title/SKU/spec rewrites with progress UI]
+ - skill: weekend-csv-products
+ owns: [Sat–Mon ordered-SKU CSV export]
+ - skill: tiktok
+ owns: [TikTok Shop sync + posting]
+ - skill: instagram-post-template
+ owns: [IG post template]
+ - skill: instagram-account-manager
+ owns: [Norma single-account control]
+ - skill: instagram-post-scheduler
+ owns: [trigger post via Norma]
+ - subagent: dw-site-build
+ - vendor_scrapers:
+ - alphabetical_skill_set: ["1838-scraper-manager", arteriors-scraper-manager, atomic50-scraper-manager,
+ bnwalls-scraper-manager, bespoke-scraper-manager, brewster-scraper-manager,
+ colefax-fowler-colorway-scraper, colouranddesign-scraper-manager, command54-scraper-manager,
+ contrado-scraper-manager, cowtan-colorway-scraper, dedar-scraper-manager,
+ denovowall-scraper-manager, designtex-scraper-manager, fabricut-scraper-manager,
+ folia-scraper-manager, franquemont-scraper-manager, hygge-scraper-manager,
+ jim-dultz-scraper-manager, justin-david-scraper, justindavid-scraper-manager,
+ knoll-scraper-manager, maya-romanoff-scraper-manager, mindthegap-scraper-manager,
+ muralsource-scraper-manager, naturale54-scraper-manager, novasuede-updater,
+ osborne-scraper-manager, reid-witlin-scraper-manager, romo-scraper-manager,
+ scalamandre-catalog-scraper, schumacher-dwsw-updater, stout-scraper-manager,
+ timorous-scraper-manager, wallquest-scraper-manager, york-scraper-manager,
+ york-wallcoverings-scraper-manager, arc-com-colorway-scraper, arte-international-colorway-scraper]
+
+ - vp: vp-directories
+ domain: Vertical directory businesses (lawyer, doctor, NPH, animals, lacountyeats, ventura)
+ triggers:
+ - lawyer | calbar | bar directory
+ - doctor | physician | professional-directory
+ - animals | pets | dogs | bowie | madison | humphrey
+ - paper hanger | wallcovering installer | NPH
+ - lacountyeats | restaurant permit
+ - ventura corridor | venturablvd
+ directors:
+ - subagent: lawyer-build-agent
+ - subagent: doctor-agent
+ - skill: ad-social-tracker
+ owns: [paid-ad detection across directories]
+ - skill: advertising-signals
+ owns: [single-domain ad scan]
+ - skill: la-research-agent # also a subagent
+ owns: [LA public records — doubles as research and lawyer enrichment]
+ - subagent: la-research-agent
+
+ - vp: vp-engineering
+ domain: Backend, frontend, databases, code review, security, performance, testing
+ triggers:
+ - backend | api | rest | graphql | microservice
+ - frontend | react | typescript | tailwind
+ - database | sql | postgres | schema | migration | n+1
+ - code review | refactor | pattern | architecture
+ - security | owasp | jwt | oauth | csrf
+ - performance | profile | cache | bottleneck
+ - test | jest | playwright | coverage
+ directors:
+ - subagent: backend-architect
+ - subagent: frontend-developer
+ - subagent: fullstack-developer
+ - subagent: database-architect
+ - subagent: database-optimizer
+ - subagent: api-documenter
+ - subagent: code-reviewer
+ - subagent: architect-reviewer
+ - subagent: security-auditor
+ - subagent: performance-engineer
+ - subagent: test-engineer
+ - subagent: error-detective
+ - subagent: debugger
+ - subagent: javascript-pro
+ - subagent: typescript-pro
+ - subagent: python-pro
+ - subagent: ios-developer
+ - subagent: mobile-developer
+ - skill: claude-api
+ owns: [Anthropic SDK migrations, prompt caching]
+ - skill: prompt-cache-optimization
+ - skill: mcp-builder
+ - skill: dw-agent-builder
+ - skill: refactor-agent
+ - skill: simplify
+ - skill: review
+
+ - vp: vp-research-content
+ domain: Web research, LA records, video production, mockups, design, voice
+ triggers:
+ - research | exa | search the web | competitor analysis
+ - mockup | concept | variant | front page
+ - peer survey | competitors | site audit | website analysis
+ - video | demo | walkthrough | reel | session debrief | avatar
+ - voice | tts | narration | clone voice
+ - logo | poster | canvas | prism
+ directors:
+ - subagent: exa-agent
+ - subagent: search-specialist
+ - subagent: technical-researcher
+ - subagent: data-analyst
+ - subagent: data-scientist
+ - subagent: website-analysis
+ - skill: site-audit
+ - skill: peer-survey
+ - skill: competitors
+ - skill: mockups
+ - skill: tools-pack
+ - skill: info-hub
+ - skill: extension
+ - skill: reviewed-demo-video
+ - skill: app-demo-video
+ - skill: session-debrief
+ - skill: video-gallery
+ - skill: clone-voice
+ - skill: use-voice
+ - skill: reels-producer
+ - skill: four-horsemen
+ - skill: four-horsemen-ui-orchestrator
+ - skill: stampede
+ - skill: canvas-design
+ - skill: artifacts-builder
+ - skill: prism
+
+ - vp: vp-compliance-policy
+ domain: Outbound comms compliance, best-practices pre-flight, legal posture
+ triggers:
+ - is this CAN-SPAM | tcpa | ccpa | dnc
+ - audit my mailer | compliance check
+ - best practices | pre-flight | violation
+ - california bar | §6155 | rule 7
+ directors:
+ - subagent: comms-compliance
+ - subagent: best-practices-reviewer
+ - skill: comms-compliance
+ - skill: best-practices
+
+architecture_principles:
+ - "Triggers should be broad enough that Steve never needs to remember which sub-agent owns a task."
+ - "When a Director is invoked twice for the same VP, consider folding the Director's logic into the VP's system prompt."
+ - "Skills are leaves — they should never be full-replaced by an agent unless that agent adds delegation logic."
+ - "Each new agent must declare what it consolidates: which skill calls or which Director it makes redundant."
+ - "Reversible steps only — agents may not push DNS, send mail, or run destructive ops without explicit Steve sign-off (echoes YOLO rules)."
+
+mindmap_path: /Users/stevestudio2/Projects/agent-cabinet/mindmap.html
+viewer_port: 9766
+last_synced_at: null
diff --git a/server.js b/server.js
new file mode 100644
index 0000000..509d74f
--- /dev/null
+++ b/server.js
@@ -0,0 +1,154 @@
+// The Cabinet viewer — serves the Mermaid mindmap of Steve's executive agent hierarchy.
+// Source: cabinet.yaml (re-rendered on each request so edits show up immediately).
+
+const fs = require('fs');
+const path = require('path');
+const http = require('http');
+
+const PORT = 9766;
+const ROOT = __dirname;
+const CABINET = path.join(ROOT, 'cabinet.yaml');
+
+function parseYaml(text) {
+ // Tiny YAML subset parser — good enough for cabinet.yaml's shape.
+ // Produces {president, cabinet:[{vp, domain, triggers:[], directors:[{skill?,subagent?,owns?}]}]}
+ const lines = text.split('\n');
+ const out = { cabinet: [] };
+ let cur = null, mode = null, trigList = null, dirList = null;
+ for (let i = 0; i < lines.length; i++) {
+ const line = lines[i];
+ if (!line.trim() || line.trim().startsWith('#')) continue;
+ const m = line.match(/^(\s*)(.+?):\s*(.*)$/);
+ if (line.match(/^ - vp:\s*(.+)$/)) {
+ cur = { vp: line.split(':')[1].trim(), triggers: [], directors: [], domain: '' };
+ out.cabinet.push(cur); mode = 'vp'; continue;
+ }
+ if (cur && mode === 'vp') {
+ if (line.match(/^ domain:\s*(.+)$/)) cur.domain = line.split(/domain:/)[1].trim();
+ else if (line.match(/^ triggers:/)) { trigList = cur.triggers; }
+ else if (line.match(/^ directors:/)) { dirList = cur.directors; trigList = null; }
+ else if (line.match(/^ - (.+)$/) && trigList) trigList.push(line.replace(/^\s*-\s*/, '').trim());
+ else if (line.match(/^ - skill:\s*(.+)$/)) dirList && dirList.push({ kind: 'skill', name: line.split(':')[1].trim() });
+ else if (line.match(/^ - subagent:\s*(.+)$/)) dirList && dirList.push({ kind: 'subagent', name: line.split(':')[1].trim() });
+ }
+ }
+ return out;
+}
+
+function buildMermaidMindmap(cabinet) {
+ const colorByVp = {
+ 'vp-operations': 'fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a',
+ 'vp-dw-commerce': 'fill:#dcfce7,stroke:#16a34a,color:#14532d',
+ 'vp-directories': 'fill:#ffedd5,stroke:#ea580c,color:#7c2d12',
+ 'vp-engineering': 'fill:#ede9fe,stroke:#7c3aed,color:#4c1d95',
+ 'vp-research-content': 'fill:#cffafe,stroke:#0891b2,color:#164e63',
+ 'vp-compliance-policy': 'fill:#fee2e2,stroke:#dc2626,color:#7f1d1d',
+ };
+ const lines = ['mindmap', ' root((Steve<br/>President))'];
+ for (const v of cabinet.cabinet) {
+ lines.push(` ${v.vp}[${v.vp}]`);
+ for (const d of v.directors.slice(0, 14)) { // cap per-VP
+ const safe = d.name.replace(/[^a-zA-Z0-9_-]/g, '');
+ const label = `${d.kind === 'skill' ? '/' : '@'}${d.name}`;
+ lines.push(` ${safe}_${v.vp}(${label})`);
+ }
+ }
+ return lines.join('\n');
+}
+
+function render(cabinet) {
+ const mm = buildMermaidMindmap(cabinet);
+ const stats = {
+ vpCount: cabinet.cabinet.length,
+ skillCount: cabinet.cabinet.reduce((a, v) => a + v.directors.filter(d => d.kind === 'skill').length, 0),
+ subagentCount: cabinet.cabinet.reduce((a, v) => a + v.directors.filter(d => d.kind === 'subagent').length, 0),
+ };
+ return `<!doctype html>
+<html><head>
+<meta charset="utf-8">
+<title>The Cabinet — Steve's executive agent hierarchy</title>
+<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
+<style>
+ body { font-family: -apple-system, BlinkMacSystemFont, sans-serif; margin: 0; background: #fafaf6; color: #111; }
+ header { padding: 28px 40px; border-bottom: 4px solid #000; background: #fff; }
+ h1 { font-size: 28px; margin: 0 0 6px; letter-spacing: -.02em; font-weight: 900; }
+ .stats { color: #555; font-size: 13px; }
+ .stats b { color: #000; }
+ main { padding: 24px 40px; }
+ .mermaid { background: #fff; border: 4px solid #000; padding: 28px; box-shadow: 6px 6px 0 #000; overflow-x: auto; }
+ footer { padding: 16px 40px 40px; color: #888; font-size: 11px; }
+ pre { background: #f5f5f0; padding: 12px; border: 2px solid #000; font-size: 11px; overflow:auto }
+ details { margin: 24px 0; }
+ summary { font-weight: 700; cursor: pointer; padding: 8px; background:#fff; border:2px solid #000; }
+ table { border-collapse: collapse; margin-top: 12px; font-size: 12px; }
+ td, th { border: 1px solid #000; padding: 6px 10px; text-align: left; vertical-align: top; }
+ th { background: #f5f5f0; }
+</style>
+</head>
+<body>
+<header>
+ <h1>The Cabinet</h1>
+ <div class="stats">
+ <b>${stats.vpCount}</b> VPs ·
+ <b>${stats.subagentCount}</b> Director subagents ·
+ <b>${stats.skillCount}</b> Director skills ·
+ Source: <code>cabinet.yaml</code> ·
+ Architect: <code>~/.claude/agents/agent-architect.md</code>
+ </div>
+</header>
+<main>
+<div class="mermaid">
+${mm}
+</div>
+
+<details>
+ <summary>Cabinet roster (table view)</summary>
+ <table>
+ <tr><th>VP</th><th>Domain</th><th>Triggers</th><th>Directors</th></tr>
+ ${cabinet.cabinet.map(v => `
+ <tr>
+ <td><b>${v.vp}</b></td>
+ <td>${v.domain || ''}</td>
+ <td>${(v.triggers || []).map(t => `<div>${t}</div>`).join('')}</td>
+ <td>${v.directors.map(d => `<div>${d.kind === 'skill' ? '/' : '@'}${d.name}</div>`).join('')}</td>
+ </tr>
+ `).join('')}
+ </table>
+</details>
+
+<details>
+ <summary>How to add a new VP / Director</summary>
+ <pre>1. Edit ~/Projects/agent-cabinet/cabinet.yaml
+2. Run: claude → "agent architect: design [role]"
+3. The architect will generate ~/.claude/agents/<name>.md
+4. Restart pm2 agent-cabinet (or refresh this page) to see the mindmap update.</pre>
+</details>
+</main>
+<footer>Steve = President · Last rendered ${new Date().toLocaleString()}</footer>
+
+<script>mermaid.initialize({startOnLoad:true, theme:'default', securityLevel:'loose', mindmap:{padding:18}});</script>
+</body></html>`;
+}
+
+const server = http.createServer((req, res) => {
+ if (req.url === '/health') { res.writeHead(200); res.end('ok'); return; }
+ if (req.url === '/cabinet.yaml') {
+ res.writeHead(200, { 'Content-Type': 'text/yaml' });
+ res.end(fs.readFileSync(CABINET, 'utf8'));
+ return;
+ }
+ try {
+ const cab = parseYaml(fs.readFileSync(CABINET, 'utf8'));
+ const html = render(cab);
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
+ res.end(html);
+ } catch (e) {
+ res.writeHead(500);
+ res.end(`Cabinet render error: ${e.message}`);
+ }
+});
+
+server.listen(PORT, '0.0.0.0', () => {
+ console.log(`The Cabinet viewer on http://localhost:${PORT}`);
+ console.log(`(also tailnet) http://100.65.187.120:${PORT}`);
+});
(oldest)
·
back to Agent Cabinet
·
Cabinet drift fix: reclassify subagents, add 9 orphans, remo 95784df →