[object Object]

← 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

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 &middot;
+    <b>${stats.subagentCount}</b> Director subagents &middot;
+    <b>${stats.skillCount}</b> Director skills &middot;
+    Source: <code>cabinet.yaml</code> &middot;
+    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/&lt;name&gt;.md
+4. Restart pm2 agent-cabinet (or refresh this page) to see the mindmap update.</pre>
+</details>
+</main>
+<footer>Steve = President &middot; 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 →