← back to Ungate Console
Ungate Console — one-page board of 35 blocked tickets grouped by who must act
24be8505cf1edab457521c9d7ccedd2d1688fdb1 · 2026-09-03 10:13:35 -0700 · Steve Abrams
Files touched
A .gitignoreA data/items.jsonA index.htmlA server.js
Diff
commit 24be8505cf1edab457521c9d7ccedd2d1688fdb1
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Sep 3 10:13:35 2026 -0700
Ungate Console — one-page board of 35 blocked tickets grouped by who must act
---
.gitignore | 5 +++
data/items.json | 43 ++++++++++++++++++++++++++
index.html | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
server.js | 40 ++++++++++++++++++++++++
4 files changed, 183 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..559785a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+node_modules/
+.env*
+*.log
+.DS_Store
+.port
diff --git a/data/items.json b/data/items.json
new file mode 100644
index 0000000..4103466
--- /dev/null
+++ b/data/items.json
@@ -0,0 +1,43 @@
+{
+ "generated": "2026-09-03T08:30:00-07:00",
+ "note": "The 35 blocked tickets after the 2026-09-03 shrink-honestly sweep (5 dead closed). Each is real; the wall is your decision list, not cruft.",
+ "items": [
+ {"tk":"TK-10029","bucket":"steve","type":"decision","title":"Rebel Walls murals: Roll → Square-Meter unit relabel","project":"dw-shopify","action":"GO on the customer-facing Shopify --apply (1467-row rollback ledger already staged). The label fix is built; only the live write is gated.","paste":""},
+ {"tk":"TK-10286","bucket":"steve","type":"credential + go-live","title":"CelebritySignatures /wear — flip apparel sales live","project":"CelebritySignatures","action":"Provide PRINTFUL_API_KEY and set WEAR_SALES_LIVE=1 / STRIPE_LIVE_ENABLED. Code-complete + safety-guarded (POD drafts only, no auto-charge). You do the flip.","paste":""},
+ {"tk":"TK-10317","bucket":"steve","type":"credential","title":"BHV AdSense approval watcher","project":"beverlyhillsvideos","action":"Wire the headless George keychain credential so the watcher can email you when the site goes live. Watcher is built + fail-loud; only the auth cred is missing.","paste":""},
+ {"tk":"TK-10337","bucket":"steve","type":"assets + Apple","title":"HomesOnSpec iOS → App Store submit","project":"homesonspec","action":"Supply 6 real-device screenshot PNGs (sim capture hangs), then authorize the ASC attach/submit. Build #2 is valid + in TestFlight.","paste":""},
+ {"tk":"TK-10387","bucket":"steve","type":"Apple","title":"dust2026 — 4 iOS apps to App Store","project":"ios","action":"Apple-account submit-for-review + metadata/screenshots. Builds exist; every remaining step is an Apple-account write only you can do.","paste":""},
+ {"tk":"TK-10402","bucket":"steve","type":"spend + credential","title":"IDS regenerate hero/scene images","project":"interiordesignershowroom","action":"Confirm/fund the Replicate token (~$6–11 for ~257 Flux images) and GO. Pipeline hardened + ready; spend + credential gated.","paste":""},
+ {"tk":"TK-10405","bucket":"steve","type":"decision","title":"Rebel Walls: 12 'Default Title' orphan variants","project":"dw-shopify","action":"Decide: leave (recommended default) vs delete (destructive productVariantsBulkDelete, restore-map ready). 10 are $4.25 sample dupes + 1 mispriced $80.48 anomaly.","paste":""},
+ {"tk":"TK-10414","bucket":"steve","type":"credential","title":"@goldleafwallpaper IG — 4h recurring poster","project":"goldleafwallpaper","action":"Provide a durable Meta Page token / app secret (current one expired). 61/61 SKUs already reposted; only the recurring token is missing.","paste":""},
+ {"tk":"TK-10427","bucket":"steve","type":"theme paste","title":"DW storefront Collection Films section","project":"dw-commerce","action":"Paste PATH-B-paste-3card.liquid into the Shopify theme editor (Step 2). Majilite collection already created + live; only the theme paste remains.","paste":""},
+ {"tk":"TK-10536","bucket":"steve","type":"value + deploy","title":"abramsagency.com landing finish","project":"abramsagency","action":"Provide the real phone number + GO on 2 prod commands (deploy + pm2 --update-env restart for lead-notify). Path B chosen; site already live.","paste":""},
+ {"tk":"TK-10631","bucket":"steve","type":"account write","title":"DW-network GA4 buildout (12 domain landers)","project":"ga-allsites","action":"Authorize GA4 property creation (Google-account write) + tag deploy. Scope re-verified down to 12; create+inject plan drafted to pending-approval.","paste":""},
+ {"tk":"TK-10740","bucket":"steve","type":"identity","title":"IG-link enrollment (5 owned accounts)","project":"Norma","action":"Perform the in-app IG↔Page links for the 5 accounts (Meta anti-hijack = unscriptable). Enrollment auto-fires the moment you link each (0/5 done).","paste":""},
+ {"tk":"TK-10742","bucket":"steve","type":"paste","title":"sample-followup launchd repoint reload","project":"sample-followup","action":"Paste the launchctl bootstrap to activate the authoritative morning drafter (plist repointed + committed 55eebea).","paste":"launchctl bootstrap gui/$(id -u) ~/Projects/sample-followup-sweep/launchd/com.steve.sample-followup-send.plist"},
+ {"tk":"TK-10758","bucket":"steve","type":"delete approval","title":"Erase 2 residual @fabric_fridays reposts","project":"dw-marketing","action":"Approve deletion of the 2 remaining sassy reposts (Brunschwig&Fils + Designtex). 114/114 primary already removed + jobs disabled; fleet-sassy-scan.js --go ready.","paste":""},
+ {"tk":"TK-10813","bucket":"steve","type":"decision","title":"GMC orphan reconcile","project":"google-merchant","action":"GO on the FRESH 162 new orphans (the approved 4569 list is stale — today's canary shows 4044 total / 162 new). Deletes GMC feed offers only, reversible via re-push.","paste":""},
+ {"tk":"TK-10836","bucket":"steve","type":"credential + Shopify","title":"Kelly Paradis 3-free-sample reissue","project":"dw-signup-fulfillment","action":"Create the DWSAMPLES3 sample-scoped discount + set RETAIL_SHARED_CODE + arm. Program is unarmed (code=null); no customer email fires until armed.","paste":""},
+ {"tk":"TK-10859","bucket":"steve","type":"Apple login","title":"Charge&Explore v1.0 REJECTED","project":"tesla","action":"Read the ASC Resolution-Center rejection reason (your login), then restore source from Henry + fix + resubmit. Also gates the Play upload (TK-10229).","paste":"cp -R /Volumes/Henry/mac2-archive/mac2-disk-offload-2026-08/tesla ~/Projects/"},
+ {"tk":"TK-10860","bucket":"steve","type":"verify / scope","title":"1281 products orderable at $0","project":"designerwallcoverings","action":"They're intentional quote-only lines. Either eyeball Shopify → Checkout → Validations (is dw-checkout-guard ON?), OR grant the token read_validations so I verify it myself, then I reframe + close. NOT a price bug.","paste":""},
+ {"tk":"TK-10866","bucket":"steve","type":"identity + delete","title":"Novasuede reels cleanup (13 reels)","project":"dw-marketing","action":"openclaw-login the 4 owning accounts + approve the 13-reel delete (irreversible). Rotation-exclusion + swatch creative already done; manifest ready.","paste":""},
+ {"tk":"TK-10878","bucket":"steve","type":"prod paste","title":"homesonspec: cut prod DB 80GB → ~25GB (+ Kamatera disk 6% reclaim)","project":"homesonspec","action":"Run the gated Kamatera disk-reclaim commands in an attended lane (unattended prod delete is classifier-blocked). Henry snapshot mirror COMPLETE + verified — the ~118G cache delete is decision-ready.","paste":""},
+ {"tk":"TK-10899","bucket":"steve","type":"send approval","title":"PJ Fall 2026 mailer go-live","project":"dw-marketing","action":"Approve the send-to-list. 2 prereqs first: (1) compliance pass (CAN-SPAM/TCPA/CCPA), (2) swap vendor-CDN hotlinks → DW-host. Then SEND or defer.","paste":""},
+ {"tk":"TK-10922","bucket":"steve","type":"FileMaker admin","title":"mfr-repair: delete 3 HSW placeholder masters","project":"mfr-review-viewer-corruption","action":"Needs a FileMaker admin repair of the relationship graph FIRST (every --apply hits error 110 'related tables missing'); the sweep executor + restore tooling are also missing from disk. Admin/identity action.","paste":""},
+ {"tk":"TK-11037","bucket":"steve","type":"decisions","title":"Pending-approval queue triage (≈29 memos)","project":"dw-ops","action":"Decide the ranked Class2/Class3 batch. Queue already swept 45→29 (reversible auto-cleared, crons closed); the remainder are genuine Steve gates.","paste":""},
+ {"tk":"TK-11041","bucket":"steve","type":"send approval","title":"Innovations re-scrape → recover 51 PR-Innovations","project":"designerwallcoverings","action":"Authorize the vendor outbound email (send-gated). Re-scrape/recover is built; only the vendor email send is held.","paste":""},
+ {"tk":"TK-11042","bucket":"steve","type":"data","title":"Track B cost-list cohorts","project":"designerwallcoverings","action":"Provide the cost/discount data (Koroseal 2448 / Maya 620 / non-Momentum PR bulk / Marburg 96). No agent calc possible without authoritative cost input.","paste":""},
+ {"tk":"TK-11127","bucket":"steve","type":"decision / gated write","title":"Resolve 5 held catalog forks","project":"dw-catalog","action":"These are NOT duplicates (proven — multiple real colorways share mfr_sku). Remaining = OK the cross-machine canonical reconciliation direction (Carnegie/Newwall/PhilRomano/Harlequin/Novasuede).","paste":""},
+
+ {"tk":"TK-10895","bucket":"external","type":"vendor cost list","title":"Quadrille / China Seas / Alan Campbell pricing","project":"dw-catalog","action":"WAITING ON VENDOR: the Quadrille mill wholesale cost list. do_not_price already set; load plan drafted. Revenue hole ~2,653 products. Nothing you can do until the list arrives.","paste":""},
+ {"tk":"TK-10670","bucket":"external","type":"vendor cost list","title":"Onboard/refresh Newmor (dist. LBI Boyd)","project":"dw","action":"WAITING ON VENDOR: the LBI Boyd cost list. 305 A/B products staged DRAFT; the .25 leak was removed. Reprice+republish once the list arrives.","paste":""},
+
+ {"tk":"TK-10372","bucket":"agent","type":"vendor-source + gated","title":"Fleet duplicate-image cross-links (final 3 products)","project":"dw-catalog","action":"AGENT/VENDOR: 8/8 reorderable already fixed; final 3 need vendor-source image acquisition + a gated Shopify media upload (no correct on-product media to reorder).","paste":""},
+ {"tk":"TK-10384","bucket":"agent","type":"recover / re-scope","title":"Butlr post-call actions branch + token fix","project":"butlr","action":"AGENT: premise unrecoverable from Mac2 — claimed commit 2d5e66f is absent everywhere, Mac1 is SSH-inaccessible, no post-call-actions spec exists. Needs Mac1 recovery or a fresh scope (may be a re-scope/close candidate).","paste":""},
+ {"tk":"TK-10550","bucket":"agent","type":"future budget","title":"RENTV Bloom sheet enrichment (add-only)","project":"rentv-sheet-enrich","action":"AGENT: last batch of 31 landed (you ran write_by_contact); ~2660 remaining is future-session grind on fresh WebSearch budget. Add-only, no email send. Loops continue it.","paste":""},
+ {"tk":"TK-10933","bucket":"agent","type":"eng bug","title":"Cron crash: com.steve.stroheim-onboard-resume","project":"cron-fire-canary","action":"AGENT/ENG: cron fires but crashes (exit 143). Real code bug, not your gate — the loops/vp-engineering can fix it.","paste":""},
+ {"tk":"TK-10993","bucket":"agent","type":"loop-cycling","title":"GMC DEGRADED remediation (feed-config)","project":"dw","action":"AGENT: durable feed-config fix, loop-cycling with actionable_pickups=0; overlaps the GMC orphan work (TK-10813). Needs consolidation, not your input.","paste":""},
+ {"tk":"TK-11092","bucket":"agent","type":"eng","title":"designerwallcoverings .git bloat 6.1GB","project":"designerwallcoverings","action":"AGENT/ENG: untrack landed but history still packed; needs a git gc / filter-repo history rewrite + stop auto-committing 47MB PNGs. Backup-size only, not customer-facing.","paste":""},
+ {"tk":"TK-11161","bucket":"agent","type":"in progress","title":"vendor-price-ingest PDF parser bug","project":"fleet-health","action":"AGENT: yoloforever-loop is actively fixing it (address-as-SKU guard added, Cody found 3 holes being closed). In progress, not your gate.","paste":""}
+ ]
+}
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..01a7f0b
--- /dev/null
+++ b/index.html
@@ -0,0 +1,95 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<title>Ungate Console</title>
+<style>
+ :root{ --bg:#0f1115; --card:#1a1d24; --card2:#20242d; --ink:#e8eaed; --dim:#9aa0ab;
+ --line:#2c313b; --steve:#ff5252; --ext:#ffb300; --agent:#7c8794; --chip:#2a3f5f; --accent:#4dd0a0; }
+ *{box-sizing:border-box}
+ body{margin:0;background:var(--bg);color:var(--ink);font:15px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif}
+ header{position:sticky;top:0;z-index:5;background:linear-gradient(180deg,#12151b,#0f1115);border-bottom:1px solid var(--line);padding:16px 22px}
+ h1{margin:0;font-size:20px;letter-spacing:.2px}
+ .sub{color:var(--dim);font-size:13px;margin-top:3px}
+ .counts{display:flex;gap:18px;margin-top:10px;flex-wrap:wrap}
+ .count{font-size:13px;color:var(--dim)}
+ .count b{font-size:22px;color:var(--ink);display:block}
+ main{max-width:1100px;margin:0 auto;padding:22px}
+ .sec{margin:28px 0 8px;display:flex;align-items:center;gap:10px}
+ .sec h2{margin:0;font-size:16px}
+ .sec .n{background:var(--card2);border:1px solid var(--line);border-radius:20px;padding:2px 11px;font-size:13px;color:var(--dim)}
+ .dot{width:11px;height:11px;border-radius:50%}
+ .grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(330px,1fr));gap:12px}
+ .card{background:var(--card);border:1px solid var(--line);border-left:4px solid var(--agent);border-radius:12px;padding:14px 15px}
+ .card.steve{border-left-color:var(--steve)}
+ .card.external{border-left-color:var(--ext)}
+ .card.agent{border-left-color:var(--agent);opacity:.9}
+ .top{display:flex;justify-content:space-between;align-items:center;gap:8px;margin-bottom:6px}
+ .tk{font-family:ui-monospace,Menlo,monospace;font-size:12px;color:var(--accent);font-weight:600}
+ .type{font-size:10.5px;text-transform:uppercase;letter-spacing:.4px;color:var(--dim);border:1px solid var(--line);border-radius:6px;padding:2px 7px;white-space:nowrap}
+ .title{font-weight:600;font-size:14.5px;margin:2px 0 4px}
+ .proj{display:inline-block;background:var(--chip);color:#cfe0ff;font-size:11px;border-radius:5px;padding:1px 7px;margin-bottom:8px}
+ .action{font-size:13.5px;color:var(--ink)}
+ .action b{color:var(--accent)}
+ .paste{margin-top:9px;background:#0b0d11;border:1px solid var(--line);border-radius:7px;padding:8px 10px;font-family:ui-monospace,Menlo,monospace;font-size:11.5px;color:#cfe0ff;position:relative;overflow-x:auto;white-space:pre}
+ .copy{position:absolute;top:5px;right:5px;background:var(--card2);border:1px solid var(--line);color:var(--dim);border-radius:6px;font-size:10.5px;padding:2px 7px;cursor:pointer}
+ .copy:hover{color:var(--ink)}
+ .hint{color:var(--dim);font-size:12.5px;margin:2px 0 14px}
+ @media (prefers-color-scheme:light){
+ :root{--bg:#f5f6f8;--card:#fff;--card2:#eef1f5;--ink:#1a1d24;--dim:#5b626e;--line:#dde1e8;--chip:#dce9ff}
+ header{background:linear-gradient(180deg,#fff,#f5f6f8)}
+ .paste{background:#f0f2f5;color:#1a3a6b}
+ }
+</style>
+</head>
+<body>
+<header>
+ <h1>🔓 Ungate Console</h1>
+ <div class="sub" id="sub">loading…</div>
+ <div class="counts" id="counts"></div>
+</header>
+<main>
+ <div class="sec"><span class="dot" style="background:var(--steve)"></span><h2>You must act</h2><span class="n" id="n-steve">0</span></div>
+ <div class="hint">Each of these is blocked ONLY on you — an approval, a credential, a value, a paste, an identity click, or a decision. These are the ones that shrink the wall.</div>
+ <div class="grid" id="g-steve"></div>
+
+ <div class="sec"><span class="dot" style="background:var(--ext)"></span><h2>Waiting on vendors / Apple</h2><span class="n" id="n-external">0</span></div>
+ <div class="hint">Nothing you can do — these move only when the outside party responds.</div>
+ <div class="grid" id="g-external"></div>
+
+ <div class="sec"><span class="dot" style="background:var(--agent)"></span><h2>Agents will finish (not yours)</h2><span class="n" id="n-agent">0</span></div>
+ <div class="hint">Open engineering / loop work parked here — the automation can complete these without you.</div>
+ <div class="grid" id="g-agent"></div>
+</main>
+<script>
+function esc(s){return (s||'').replace(/[&<>]/g,c=>({'&':'&','<':'<','>':'>'}[c]))}
+function card(it){
+ const paste = it.paste ? `<div class="paste"><button class="copy" onclick="navigator.clipboard.writeText(this.parentNode.dataset.p);this.textContent='copied'">copy</button>${esc(it.paste)}</div>` : '';
+ const el = document.createElement('div');
+ el.className = 'card '+it.bucket;
+ el.innerHTML = `<div class="top"><span class="tk">${esc(it.tk)}</span><span class="type">${esc(it.type)}</span></div>
+ <div class="title">${esc(it.title)}</div>
+ <span class="proj">${esc(it.project)}</span>
+ <div class="action">→ ${esc(it.action)}</div>${paste}`;
+ if(it.paste){ el.querySelector('.paste').dataset.p = it.paste; }
+ return el;
+}
+fetch('/api/items').then(r=>r.json()).then(d=>{
+ const by={steve:[],external:[],agent:[]};
+ d.items.forEach(it=>by[it.bucket].push(it));
+ ['steve','external','agent'].forEach(b=>{
+ const g=document.getElementById('g-'+b);
+ by[b].forEach(it=>g.appendChild(card(it)));
+ document.getElementById('n-'+b).textContent=by[b].length;
+ });
+ document.getElementById('sub').textContent =
+ `${d.items.length} blocked tickets · generated ${new Date(d.generated).toLocaleString(undefined,{month:'short',day:'numeric',hour:'numeric',minute:'2-digit'})}`;
+ document.getElementById('counts').innerHTML =
+ `<div class="count"><b style="color:var(--steve)">${by.steve.length}</b>need you</div>`+
+ `<div class="count"><b style="color:var(--ext)">${by.external.length}</b>vendors/Apple</div>`+
+ `<div class="count"><b style="color:var(--agent)">${by.agent.length}</b>agents</div>`;
+});
+</script>
+</body>
+</html>
diff --git a/server.js b/server.js
new file mode 100644
index 0000000..696cbc1
--- /dev/null
+++ b/server.js
@@ -0,0 +1,40 @@
+#!/usr/bin/env node
+// Ungate Console — one page of everything blocked, grouped by who must act.
+// Zero-dep, Basic-auth admin/DW2024!, OS-assigned free port.
+const http = require('http');
+const fs = require('fs');
+const path = require('path');
+
+const USER = process.env.UC_USER || 'admin';
+const PASS = process.env.UC_PASS || 'DW2024!';
+const DIR = __dirname;
+
+function auth(req, res) {
+ const h = req.headers.authorization || '';
+ const [, b64] = h.split(' ');
+ const [u, p] = Buffer.from(b64 || '', 'base64').toString().split(':');
+ if (u === USER && p === PASS) return true;
+ res.writeHead(401, { 'WWW-Authenticate': 'Basic realm="ungate-console"' });
+ res.end('auth required');
+ return false;
+}
+
+const srv = http.createServer((req, res) => {
+ if (!auth(req, res)) return;
+ const url = req.url.split('?')[0];
+ if (url === '/api/items') {
+ res.writeHead(200, { 'Content-Type': 'application/json' });
+ return res.end(fs.readFileSync(path.join(DIR, 'data', 'items.json')));
+ }
+ if (url === '/' || url === '/index.html') {
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
+ return res.end(fs.readFileSync(path.join(DIR, 'index.html')));
+ }
+ res.writeHead(404); res.end('not found');
+});
+
+srv.listen(0, '127.0.0.1', () => {
+ const port = srv.address().port;
+ fs.writeFileSync(path.join(DIR, '.port'), String(port));
+ console.log(`Ungate Console → http://127.0.0.1:${port} (admin/DW2024!)`);
+});
(oldest)
·
back to Ungate Console
·
Ungate Console: per-card GO/Defer/Close selection + decision e063e7f →