← back to AbramsEgo
auto-save: 2026-07-01T12:12:34 (4 files) — build-queue/STOP build-queue/tasks/06a-cards-datetime.md public/index.html build-queue/failed/06a-cards-datetime.md
79460f7fdd7142eeb4f03eb2ee9d441dba91a396 · 2026-07-01 12:12:35 -0700 · Steve Abrams
Files touched
D build-queue/STOPR100 build-queue/tasks/06a-cards-datetime.md build-queue/failed/06a-cards-datetime.mdM public/index.html
Diff
commit 79460f7fdd7142eeb4f03eb2ee9d441dba91a396
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Wed Jul 1 12:12:35 2026 -0700
auto-save: 2026-07-01T12:12:34 (4 files) — build-queue/STOP build-queue/tasks/06a-cards-datetime.md public/index.html build-queue/failed/06a-cards-datetime.md
---
build-queue/STOP | 0
.../{tasks => failed}/06a-cards-datetime.md | 0
public/index.html | 75 +++++++++++++++-------
3 files changed, 52 insertions(+), 23 deletions(-)
diff --git a/build-queue/STOP b/build-queue/STOP
deleted file mode 100644
index e69de29..0000000
diff --git a/build-queue/tasks/06a-cards-datetime.md b/build-queue/failed/06a-cards-datetime.md
similarity index 100%
rename from build-queue/tasks/06a-cards-datetime.md
rename to build-queue/failed/06a-cards-datetime.md
diff --git a/public/index.html b/public/index.html
index 59a8883..4e2098d 100644
--- a/public/index.html
+++ b/public/index.html
@@ -136,6 +136,7 @@
<!-- CANARIES -->
<section class="card span4">
<h2>🐤 Canary board</h2>
+ <div id="canaries-ctl"></div>
<div class="list" id="canaries"></div>
</section>
@@ -184,7 +185,8 @@
<!-- CRON / LAUNCHD (panel 4) — every scheduled com.steve.* job as an admin card -->
<section class="card span12">
<h2>⏱ Cron / launchd <span class="muted" id="crons-sub"></span></h2>
- <div id="crongrid" style="display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:10px"></div>
+ <div id="crongrid-ctl"></div>
+ <div id="crongrid" style="display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:10px;max-height:560px;overflow:auto"></div>
</section>
<!-- AI CHAT -->
@@ -322,13 +324,9 @@ async function load(){
$('loc-up').innerHTML=`<span class="good">${l.up??'—'}</span><span class="dim" style="font-size:16px">/${l.total??'—'} up</span>`;
$('loc-list').innerHTML=(l.procs||[]).map(pr=>lrow(`${statusDot(pr.status)}${esc(pr.name)}`,`${pr.memMB!=null?pr.memMB+'M':''}`,whenChip(pr.startedAt))).join('')||'<span class="muted">no local pm2 procs</span>';
- // ---- canaries ----
+ // ---- canaries ---- (sort + density + infinite scroll like every DW grid)
const cans=(d.canaries&&d.canaries.canaries)||[];
- $('canaries').innerHTML=cans.map(cn=>{
- const v=(cn.verdict||'').toUpperCase();
- const col=/FAIL|DOWN|CRIT/.test(v)?'bad':/WARN|DEGRAD/.test(v)?'warn':/PASS|UP|HEALTH|OK/.test(v)?'good':'dim';
- return lrow(esc(cn.name),`<span class="${col}">${esc(cn.verdict||'—')}</span> <span class="dim">${cn.ageMin}m${cn.stale?' ⚠':''}</span>`,whenChip(cn.mtime,cn.scanned));
- }).join('')||'<span class="muted">no canaries</span>';
+ renderCanaries(cans);
// ---- crons / officers ----
const cr=d.crons||{};
@@ -459,27 +457,58 @@ function renderActivity(d){
// PID · idle=grey · nonzero-exit=red.
function renderCrons(d){
const cr=d.crons||{};
- const jobs=(cr.jobs||[]).slice().sort((a,b)=>String(a.label).localeCompare(String(b.label)));
+ const jobs=cr.jobs||[];
$('crons-sub').textContent=`· ${cr.loadedCount??0} loaded / ${cr.count??0} total · com.steve.*`;
- const el=$('crongrid'); if(!el) return;
- const pill=(j)=>{
+ const cronPill=(j)=>{
if(j.state==='running') return `<span class="pill live">▶ running · ${esc(j.pid)}</span>`;
if(j.state==='error') return `<span class="pill" style="color:var(--bad);border-color:#ff5d6c44;background:#ff5d6c0f">✕ exit ${esc(j.lastExit)}</span>`;
return `<span class="pill">idle</span>`;
};
- el.innerHTML=jobs.map(j=>{
- const iso=j.created||j.modified||'';
- const dt=iso?new Date(iso):null;
- const when=dt?dt.toLocaleString(undefined,{year:'numeric',month:'short',day:'numeric',hour:'numeric',minute:'2-digit'}):'—';
- const name=String(j.label||'').replace(/^com\.steve\./,'');
- const sched=j.schedule?`⏲ ${esc(j.schedule)}`:'<span class="dim">no schedule</span>';
- const prog=j.program?` · <span class="dim">${esc(j.program)}</span>`:'';
- return `<div class="subcard" title="created ${esc(iso)}">
- <div class="subcard-top"><span class="subcard-proj">${esc(name)}</span>${pill(j)}</div>
- <div class="subcard-when" style="margin-top:6px">${sched}${prog}</div>
- <div class="subcard-when">🕓 ${esc(when)}</div>
- </div>`;
- }).join('')||'<span class="muted">no com.steve.* jobs</span>';
+ const cronRank=(j)=> j.state==='error'?0 : j.state==='running'?1 : 2;
+ initGrid('crons',{
+ controlsHost:$('crongrid-ctl'), host:$('crongrid'), batch:18, minCols:1, maxCols:6, defaultCols:4,
+ empty:'no com.steve.* jobs',
+ sortModes:[
+ {k:'new', label:'Newest', cmp:(a,b)=>tsOf(b.created,b.modified)-tsOf(a.created,a.modified)},
+ {k:'old', label:'Oldest', cmp:(a,b)=>tsOf(a.created,a.modified)-tsOf(b.created,b.modified)},
+ {k:'name', label:'Name A→Z', cmp:(a,b)=>String(a.label||'').localeCompare(String(b.label||''))},
+ {k:'stat', label:'Status', cmp:(a,b)=>cronRank(a)-cronRank(b)||String(a.label||'').localeCompare(String(b.label||''))},
+ ],
+ render:(j)=>{
+ const iso=j.created||j.modified||'';
+ const name=String(j.label||'').replace(/^com\.steve\./,'');
+ const sched=j.schedule?`⏲ ${esc(j.schedule)}`:'<span class="dim">no schedule</span>';
+ const prog=j.program?` · <span class="dim">${esc(j.program)}</span>`:'';
+ return `<div class="subcard" title="created ${esc(iso)}">
+ <div class="subcard-top"><span class="subcard-proj">${esc(name)}</span>${cronPill(j)}</div>
+ <div class="subcard-when" style="margin-top:6px">${sched}${prog}</div>
+ <div class="subcard-when">${whenChip(j.created,j.modified)||'🕓 —'}</div>
+ </div>`;
+ },
+ });
+ feedGrid('crons', jobs);
+}
+// canary board — each canary is a card with a created/scanned date+time; grid
+// gets sort + density + infinite scroll (verdict/staleness/name modes).
+function renderCanaries(cans){
+ const vrank=(cn)=>{ const v=(cn.verdict||'').toUpperCase();
+ return /FAIL|DOWN|CRIT/.test(v)?0:/WARN|DEGRAD/.test(v)?1:/PASS|UP|HEALTH|OK/.test(v)?2:3; };
+ initGrid('canaries',{
+ controlsHost:$('canaries-ctl'), host:$('canaries'), batch:20, minCols:1, maxCols:3, defaultCols:1,
+ empty:'no canaries',
+ sortModes:[
+ {k:'new', label:'Newest', cmp:(a,b)=>tsOf(b.mtime,b.scanned)-tsOf(a.mtime,a.scanned)},
+ {k:'verdict',label:'Verdict', cmp:(a,b)=>vrank(a)-vrank(b)||(a.name||'').localeCompare(b.name||'')},
+ {k:'stale', label:'Staleness', cmp:(a,b)=>(b.ageMin||0)-(a.ageMin||0)},
+ {k:'name', label:'Name A→Z', cmp:(a,b)=>(a.name||'').localeCompare(b.name||'')},
+ ],
+ render:(cn)=>{
+ const v=(cn.verdict||'').toUpperCase();
+ const col=/FAIL|DOWN|CRIT/.test(v)?'bad':/WARN|DEGRAD/.test(v)?'warn':/PASS|UP|HEALTH|OK/.test(v)?'good':'dim';
+ return lrow(esc(cn.name),`<span class="${col}">${esc(cn.verdict||'—')}</span> <span class="dim">${cn.ageMin}m${cn.stale?' ⚠':''}</span>`,whenChip(cn.mtime,cn.scanned));
+ },
+ });
+ feedGrid('canaries', cans);
}
function statusDot(st){const c=st==='online'?'var(--good)':st?'var(--bad)':'var(--dim)';return `<span class="dot" style="background:${c}"></span>`;}
function fmtDur(s){if(s==null)return null;if(s<60)return s+'s';if(s<3600)return Math.floor(s/60)+'m';return Math.floor(s/3600)+'h';}
← 6268895 queue: re-split timed-out 06 into 06a (card date+time) + 06b
·
back to AbramsEgo
·
chore: replenish build queue (2 tasks + replenisher) 3031aa5 →