← back to Gated Morning Review
viewer v3: add 'What I'd do' suggested-action column (12yr plain language, old/stale + task-status aware)
4708dcbccf7d0626911594d096668596fa927ad6 · 2026-08-20 09:18:46 -0700 · steve
Files touched
Diff
commit 4708dcbccf7d0626911594d096668596fa927ad6
Author: steve <steve@designerwallcoverings.com>
Date: Thu Aug 20 09:18:46 2026 -0700
viewer v3: add 'What I'd do' suggested-action column (12yr plain language, old/stale + task-status aware)
---
lib.mjs | 34 ++++++++++++++++++++++++----------
server.mjs | 3 +++
2 files changed, 27 insertions(+), 10 deletions(-)
diff --git a/lib.mjs b/lib.mjs
index 4cd044c..4580f04 100644
--- a/lib.mjs
+++ b/lib.mjs
@@ -27,31 +27,38 @@ const CAT = {
golive: { big: '🌐 Put something LIVE on the internet',
why: "Right now this thing is NOT online where people can see it. This puts it live on the web.",
good: "More people can find and use it — could bring visitors or sales.",
- bad: "Going live is hard to undo (it changes DNS + servers). If it's not ready, or it's already live, skip it." },
+ bad: "Going live is hard to undo (it changes DNS + servers). If it's not ready, or it's already live, skip it.",
+ sug: "🙋 YOU do this one — it goes LIVE to everyone. Make sure it's really ready first." },
money: { big: '💳 Money / payments',
why: "This is about REAL money — turning on charging, or fixing a price that's wrong.",
good: "Stops us losing money or lets us start earning.",
- bad: "Real money = real risk. If the numbers are old, it could charge or price the wrong amount." },
+ bad: "Real money = real risk. If the numbers are old, it could charge or price the wrong amount.",
+ sug: "🙋 Needs YOU — it's real money. Only run it if the numbers are fresh." },
store: { big: '🏷️ Change the online store (shoppers see it)',
why: "This changes what shoppers see in the store — a product, a price, a picture, or a link.",
good: "Makes the store correct so shoppers see the right thing (and Google is happy).",
- bad: "It's LIVE to customers. If the info inside is old, it could change the wrong products." },
+ bad: "It's LIVE to customers. If the info inside is old, it could change the wrong products.",
+ sug: "✅ Usually safe to run — it's a small store fix you can undo." },
system: { big: '🔧 System / security setup',
why: "This sets up something behind the scenes — a server, a timer/schedule, or a password.",
good: "Keeps the machines healthy, safe, and running on their own.",
- bad: "Touches servers or passwords. Done at the wrong time it can break things or make a duplicate job." },
+ bad: "Touches servers or passwords. Done at the wrong time it can break things or make a duplicate job.",
+ sug: "🙋 Your hands — it touches servers or passwords. Safe, but needs you." },
social: { big: '📣 Social-media posting',
why: "This posts something to a PUBLIC social account (like Instagram or TikTok).",
good: "Gets our stuff seen by lots more people for free.",
- bad: "It's public and hard to unsend. A wrong or repeated post looks bad." },
+ bad: "It's public and hard to unsend. A wrong or repeated post looks bad.",
+ sug: "📣 Only if you're sure — a public post is hard to un-post." },
send: { big: '✉️ Send a message to someone',
why: "This sends an email or message OUT to a person (a customer or a vendor).",
good: "Reaches someone we actually need to talk to.",
- bad: "Once it's sent you can't unsend it — make sure it's right and wanted first." },
+ bad: "Once it's sent you can't unsend it — make sure it's right and wanted first.",
+ sug: "✉️ Only if it's right — you can't unsend an email." },
other: { big: '📋 A change that needs your OK',
why: "This is a change someone set up that's waiting for your yes-or-no.",
good: "Ticks a to-do off the list.",
- bad: "If it's old or already handled, it's just clutter — safe to toss." },
+ bad: "If it's old or already handled, it's just clutter — safe to toss.",
+ sug: "🤔 Just pick yes or no — it's a choice, not a chore." },
};
export function classify(title, head, file) {
@@ -66,7 +73,7 @@ export function classify(title, head, file) {
else if (has(/instagram|\big\b|tiktok|youtube|social|post batch|roster|@\w/)) key = 'social';
else if (has(/\bemail\b|\bsend\b|blast|letter|nudge|mailer/)) key = 'send';
const c = CAT[key];
- return { category: key, big: c.big, why: c.why, good: c.good, bad: c.bad, staleSig };
+ return { category: key, big: c.big, why: c.why, good: c.good, bad: c.bad, sug: c.sug, staleSig };
}
export function scanQueue() {
@@ -84,9 +91,13 @@ export function scanQueue() {
const aging = age >= AGING_DAYS;
// aging items get an extra "stale-data" warning appended to the bad reason
const bad = aging ? c.bad + " ⚠️ And it's OLD — the info inside may be out of date, so re-check before running." : c.bad;
+ // my suggestion, in plain kid words — with an old/stale overlay
+ const suggest = c.staleSig ? "🗑️ Probably already done — safe to toss."
+ : aging ? "⚠️ It's OLD — first make sure the info is still true, THEN " + c.sug.replace(/^..? /, "").toLowerCase()
+ : c.sug;
return { kind: 'gated', id: f, file: f, title, ticket, age,
ageWord: age <= 0 ? 'today' : age === 1 ? '1 day old' : `${age} days old`,
- ...c, bad, aging, disposition: (c.staleSig || age > STALE_DAYS) ? 'STALE' : 'DECIDE' };
+ ...c, bad, suggest, aging, disposition: (c.staleSig || age > STALE_DAYS) ? 'STALE' : 'DECIDE' };
}).filter(Boolean).sort((a, b) => b.age - a.age);
}
@@ -101,8 +112,11 @@ export function scanTasks(limit = 60) {
if (!m) continue;
const [, id, status, owner, project, title] = m;
const c = classify(title, '', id);
+ const suggest = status === 'blocked' ? "⏳ Stuck waiting on something else — can't run it yet."
+ : status === 'doing' ? "⚙️ A robot's already working on it — leave it alone."
+ : c.sug;
items.push({ kind: 'task', id, status, owner, project, title: title.slice(0, 140),
- ...c, blocked: status === 'blocked', doing: status === 'doing' });
+ ...c, suggest, blocked: status === 'blocked', doing: status === 'doing' });
if (items.length >= limit) break;
}
return items;
diff --git a/server.mjs b/server.mjs
index 78343b8..e7e465d 100644
--- a/server.mjs
+++ b/server.mjs
@@ -66,6 +66,7 @@ const card = (it) => {
<div class=raw>${(it.title||'').replace(/</g,'<')}</div></div>
<div class=col><div class=lbl>👍 Good reason to keep & run</div><div class="txt gd">${it.good}</div>
<div class=lbl style=margin-top:10px>👎 Reason it's OK to close</div><div class="txt bd">${it.bad}</div></div>
+ <div class="col sugcol"><div class=lbl>🤔 What I'd do</div><div class="txt sg">${it.suggest||''}</div></div>
</div>
<div class=btns>
<button class=run onclick="run('${runId}','${it.kind}',this)">▶️ Run in iTerm2</button>
@@ -91,6 +92,8 @@ h1{font-size:38px;margin:6px 0}.sub{font-size:20px;color:#6b6257;margin-bottom:1
.cols{display:flex;gap:18px;flex-wrap:wrap}.col{flex:1;min-width:260px}
.lbl{font-size:15px;font-weight:800;color:#6b6257;text-transform:uppercase;letter-spacing:.3px}
.txt{font-size:18px;margin:3px 0 0}.gd{color:#1f6b3a}.bd{color:#8a4b12}
+.sugcol{background:#fff8e6;border:2px solid #f0d98a;border-radius:12px;padding:12px 14px;min-width:230px}
+.sg{font-size:19px;font-weight:700;color:#5b4a12}
.raw{font-size:13px;color:#9a8f80;margin-top:8px;word-break:break-word}
.btns{display:flex;gap:12px;margin-top:16px}
button{font-size:20px;font-weight:700;padding:14px 20px;border:0;border-radius:13px;cursor:pointer;flex:1}
← bc59465 viewer: honest Run-button note — queues to _approved + loop
·
back to Gated Morning Review
·
morning-review: dedupe queue — hide tasks that duplicate a g e3a8b5e →