[object Object]

← back to Claude Codex Meeting

fix(run-meeting): apply 3-way debate consensus patches

858ca1fc47190854b86c28d77cfcf33bbbdd2e46 · 2026-05-01 14:36:13 -0700 · Steve

The codex+claude+qwen debate (round 1-7, run codex-meeting-3way-2026-05-01)
converged on one architectural insight: the pipeline had no content-quality
gate between `claude --print` output and George email send, so a
hallucinated tool-failure footer ("the write was blocked by permissions")
shipped to email AND poisoned the carryover chain by being fed back into
the next meeting's prompt as "prior context."

Patches applied:

CRITICAL (the gap):
- is_leaked_meta() content-sniff before symlink update + email send. On hit,
  status=leaked-meta, run quarantined, carryover stays clean. Patterns match
  the "Here's the digest, I'll paste it directly", "the write was blocked",
  "I cannot/can't write" failure modes from claude --print.
- strip_leaked_meta() sanitizes carryover when reading $LAST so a
  contaminated prior meeting can't infect the next prompt.
- claude --print --disallowedTools 'Write Edit Read Bash' belt-and-suspenders
  so the model can't even attempt the failed tool call that produced the
  footer in the first place.

HIGH:
- Hardcoded 'admin:DWSecure2024!' fallback removed. GEORGE_AUTH now read
  from $GEORGE_AUTH env or ~/Projects/secrets-manager/.env exclusively;
  email skipped if neither has it. (Credential added to secrets-manager
  outside this commit.)
- curl -sf health probe → curl -s so HTTP 401 reaches the grep gate
  instead of being killed by -f + pipefail (the dead-code path).
- TS=%H%M → %H%M%S so two cadences in the same minute can't clobber.
- last-meeting.md is now a relative symlink (meetings/...md) instead of
  absolute, so it survives clone/move. ln -sfn is atomic via rename(2)
  under the hood; flock removed (macOS lacks it, seconds-precision +
  hour-spaced cadences make the within-minute race impossible).
- email.log is NDJSON now: one record per line with ts, meeting,
  type, chars, resp. Joinable on meeting filename across logs.
- sunday-digest hard-gate on dow=Sunday unless FORCE=1 (the round-2
  finding: a Friday-fired digest can't accidentally mass-mail).

MEDIUM:
- printf '%s\n' instead of echo for the prompt pipe (preserves leading -e
  / -n / backslash if a future prompt edit starts with a dash).
- find -maxdepth before -name (BSD find ordering on macOS).
- while IFS= read -r f instead of bare read.
- git log %ar truncated by character (awk substr) instead of bytes
  (head -c) so multibyte em-dash doesn't split.

Quarantined the contaminated 2026-05-01_1316-sunday-digest.md to
meetings/.quarantine/ and converted email.log to NDJSON in place
(legacy concatenated copy at logs/email.log.legacy.bak).

Verified end-to-end on the 14:34:39 morning re-fire: status=ok,
symlink relative, email landed (msg 19de577ab72badf9), NDJSON parses
via jq.

Debate run logs: ~/.claude/skills/claude-codex/runs/codex-meeting-3way-2026-05-01/

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit 858ca1fc47190854b86c28d77cfcf33bbbdd2e46
Author: Steve <steve@designerwallcoverings.com>
Date:   Fri May 1 14:36:13 2026 -0700

    fix(run-meeting): apply 3-way debate consensus patches
    
    The codex+claude+qwen debate (round 1-7, run codex-meeting-3way-2026-05-01)
    converged on one architectural insight: the pipeline had no content-quality
    gate between `claude --print` output and George email send, so a
    hallucinated tool-failure footer ("the write was blocked by permissions")
    shipped to email AND poisoned the carryover chain by being fed back into
    the next meeting's prompt as "prior context."
    
    Patches applied:
    
    CRITICAL (the gap):
    - is_leaked_meta() content-sniff before symlink update + email send. On hit,
      status=leaked-meta, run quarantined, carryover stays clean. Patterns match
      the "Here's the digest, I'll paste it directly", "the write was blocked",
      "I cannot/can't write" failure modes from claude --print.
    - strip_leaked_meta() sanitizes carryover when reading $LAST so a
      contaminated prior meeting can't infect the next prompt.
    - claude --print --disallowedTools 'Write Edit Read Bash' belt-and-suspenders
      so the model can't even attempt the failed tool call that produced the
      footer in the first place.
    
    HIGH:
    - Hardcoded 'admin:DWSecure2024!' fallback removed. GEORGE_AUTH now read
      from $GEORGE_AUTH env or ~/Projects/secrets-manager/.env exclusively;
      email skipped if neither has it. (Credential added to secrets-manager
      outside this commit.)
    - curl -sf health probe → curl -s so HTTP 401 reaches the grep gate
      instead of being killed by -f + pipefail (the dead-code path).
    - TS=%H%M → %H%M%S so two cadences in the same minute can't clobber.
    - last-meeting.md is now a relative symlink (meetings/...md) instead of
      absolute, so it survives clone/move. ln -sfn is atomic via rename(2)
      under the hood; flock removed (macOS lacks it, seconds-precision +
      hour-spaced cadences make the within-minute race impossible).
    - email.log is NDJSON now: one record per line with ts, meeting,
      type, chars, resp. Joinable on meeting filename across logs.
    - sunday-digest hard-gate on dow=Sunday unless FORCE=1 (the round-2
      finding: a Friday-fired digest can't accidentally mass-mail).
    
    MEDIUM:
    - printf '%s\n' instead of echo for the prompt pipe (preserves leading -e
      / -n / backslash if a future prompt edit starts with a dash).
    - find -maxdepth before -name (BSD find ordering on macOS).
    - while IFS= read -r f instead of bare read.
    - git log %ar truncated by character (awk substr) instead of bytes
      (head -c) so multibyte em-dash doesn't split.
    
    Quarantined the contaminated 2026-05-01_1316-sunday-digest.md to
    meetings/.quarantine/ and converted email.log to NDJSON in place
    (legacy concatenated copy at logs/email.log.legacy.bak).
    
    Verified end-to-end on the 14:34:39 morning re-fire: status=ok,
    symlink relative, email landed (msg 19de577ab72badf9), NDJSON parses
    via jq.
    
    Debate run logs: ~/.claude/skills/claude-codex/runs/codex-meeting-3way-2026-05-01/
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
 .symlink.lock                                      |   0
 last-meeting.md                                    |   2 +-
 logs/2026-05-01_1316-sunday-digest.context.md      | 123 +++++++++++++++++++
 logs/2026-05-01_1325-morning.context.md            | 136 +++++++++++++++++++++
 logs/2026-05-01_143253-morning.context.md          | 121 ++++++++++++++++++
 logs/2026-05-01_143439-morning.context.md          | 121 ++++++++++++++++++
 logs/email.log                                     |   5 +-
 logs/email.log.legacy.bak                          |   1 +
 logs/run.log                                       |  29 +++++
 .../.quarantine/2026-05-01_1316-sunday-digest.md   |  69 +++++++++++
 meetings/2026-05-01_1325-morning.md                |  54 ++++++++
 meetings/2026-05-01_143439-morning.md              |  56 +++++++++
 run-meeting.sh                                     | 133 ++++++++++++++++----
 13 files changed, 822 insertions(+), 28 deletions(-)

diff --git a/.symlink.lock b/.symlink.lock
new file mode 100644
index 0000000..e69de29
diff --git a/last-meeting.md b/last-meeting.md
index b4f8b82..8a2f8ae 120000
--- a/last-meeting.md
+++ b/last-meeting.md
@@ -1 +1 @@
-/Users/stevestudio2/Projects/claude-codex-meeting/meetings/2026-05-01_1305-morning.md
\ No newline at end of file
+meetings/2026-05-01_143439-morning.md
\ No newline at end of file
diff --git a/logs/2026-05-01_1316-sunday-digest.context.md b/logs/2026-05-01_1316-sunday-digest.context.md
new file mode 100644
index 0000000..5978121
--- /dev/null
+++ b/logs/2026-05-01_1316-sunday-digest.context.md
@@ -0,0 +1,123 @@
+## Meeting context — sunday-digest — Fri 2026-05-01 13:16 PDT
+
+### Last meeting carryover
+Using the context bundle provided directly in the prompt — here is today's meeting.
+
+---
+
+## Daily Stand-Up — Fri 2026-05-01
+
+---
+
+### 1. Carryover from last meeting
+_No prior meeting on file. Clean slate._
+
+---
+
+### 2. Overnight (last 12 hours)
+
+**Crashes / instability** — multiple unstable processes:
+
+- ⚠️ `am-recrawl` — **stopped**, 90 restarts. Highest urgency. Not recovering on its own; likely a hard error (bad endpoint, auth expiry, or out-of-memory loop). Needs manual inspection before re-enabling.
+- ⚠️ `pd-api` — online but 23 restarts. Professionals directory API is flapping; probably tied to the LA County doctors project (committed 2 days ago). App-level crash, not infra.
+- ⚠️ `animals-viewer` — online, 21 restarts. A near-me SQL fix was just committed 3 minutes ago — this may settle. Watch it.
+- ⚠️ `visual-factory-orchestrator` — online, 16 restarts. A socket prefetch fix was pushed 13h ago (`agent:false`). May be stabilizing; restart count doesn't show post-fix window.
+- ⚠️ `george-gmail` — online but only 1h uptime, 3 restarts. Email infra is fragile right now.
+- `sf-orchestrator` — 7 restarts (not in top-30 list, flagged in crash list only). Needs a log pull.
+- `gemini-catalog-tagger` — 6 restarts in 4h. Tagging pipeline is actively struggling.
+
+**Long-running jobs** — `gemini-tag-engine` has been running 11h (1 restart, appears stable). `full-monty-agent`, `gap-agent`, `update-sku-agent` all stable at 28h uptime.
+
+**External signals** — all git activity is local (Steve). No collaborator commits. Visual-factory prefetch fix and animals SQL fix both landed overnight/just now.
+
+---
+
+### 3. Today's plan + agent assignments
+
+1. `Steve` — inspect `am-recrawl` logs (`pm2 logs am-recrawl --lines 50`) — 90 restarts means a hard loop; determine if it's an auth expiry or bad target URL — **success: root cause identified, process either restarted clean or stopped intentionally**
+2. `debugger-agent` — pull `pd-api` crash logs and identify why it's flapping at 23 restarts — probably a missing env var or DB connection string in the new professional-directory project — **success: error type identified, fix scoped**
+3. `Steve` — verify `animals-viewer` stabilizes after the near-me SQL fix committed 3min ago — just watch pm2 restart count for 30 min — **success: restarts stop climbing**
+4. `Steve` — check `george-gmail` (1h uptime, 3 restarts) — email infra failure could silently kill outbound comms — **success: logs reviewed, process stable or root cause surfaced**
+5. `gemini-catalog-tagger` — if still restarting after #2 is scoped: pause it and run `gemini-tag-engine` solo until tagger is fixed — **success: tagging pipeline producing output without crash loop**
+6. `Steve` — review lawyer-directory dashboard changes (committed 35h ago) for the wiki-lawyers importer — **success: confirm wiki source data is pulling correctly, no false positives in the import**
+
+---
+
+### 4. Blockers & decisions Steve owes
+
+- `am-recrawl` restart: can't auto-recover at 90 restarts — Steve must decide restart-or-disable.
+- `pd-api` / professional-directory: new project with no prior context — Steve needs to confirm whether this is production or still dev (affects urgency of the flapping fix).
+- `visual-factory-orchestrator` — 16 restarts: is the socket fix sufficient or does this need a deeper architectural review?
+- FashionCrawler TODO content was truncated — unknown open items there.
+
+---
+
+### 5. One thing to think about
+
+`pd-api` (professionals directory) and `lawyer-directory-builder` are both new directory projects committing in parallel. Are these the same product family or separate initiatives — and if separate, are they sharing infra/DB, or is that a gap that'll bite you at launch?
+
+### PM2 fleet status (top 30)
+- slack-dm-viewer online restarts=0 uptime=28h
+- sku-check-skill online restarts=0 uptime=28h
+- kamatera-tunnels online restarts=0 uptime=28h
+- dex-dedup-agent online restarts=0 uptime=28h
+- color-search online restarts=0 uptime=28h
+- dw-central online restarts=0 uptime=28h
+- hormuz-orchestrator online restarts=0 uptime=28h
+- yolo-agent online restarts=0 uptime=28h
+- silas-sku-agent online restarts=0 uptime=28h
+- vendor-command-center online restarts=1 uptime=28h
+- vendor-onboarding online restarts=1 uptime=28h
+- room-setting-agent online restarts=0 uptime=28h
+- shopify-expert-agent online restarts=0 uptime=28h
+- momentum-pricer online restarts=0 uptime=28h
+- shopify-queue-worker online restarts=0 uptime=28h
+- norma-bluesky online restarts=1 uptime=28h
+- norma-facebook online restarts=1 uptime=28h
+- norma-instagram online restarts=1 uptime=28h
+- norma-twitter online restarts=1 uptime=28h
+- norma-price online restarts=1 uptime=28h
+- george-gmail online restarts=3 uptime=1h
+- archive-agent online restarts=0 uptime=28h
+- timeout-agent online restarts=0 uptime=28h
+- plumbing-agent online restarts=0 uptime=28h
+- update-sku-agent online restarts=0 uptime=28h
+- vendor-discount-agent online restarts=1 uptime=28h
+- claudette-agent online restarts=0 uptime=28h
+- gemini-classifier online restarts=0 uptime=28h
+- am-recrawl stopped restarts=90 uptime=14h
+- blog-agent online restarts=0 uptime=28h
+- full-monty-agent online restarts=0 uptime=28h
+- gap-agent online restarts=0 uptime=28h
+- gemini-tag-engine online restarts=1 uptime=11h
+- gemini-catalog-tagger online restarts=6 uptime=4h
+- graphic-agent online restarts=0 uptime=28h
+- launch-supervisor online restarts=0 uptime=28h
+- product-agent online restarts=0 uptime=28h
+- hawke online restarts=0 uptime=28h
+- artie-agent online restarts=0 uptime=28h
+- garrett online restarts=0 uptime=28h
+
+### Crashed/unstable agents (last 24h, restart_time>3 OR errored)
+- am-recrawl status=stopped restarts=90
+- gemini-catalog-tagger status=online restarts=6
+- sf-orchestrator status=online restarts=7
+- visual-factory-orchestrator status=online restarts=16
+- pd-api status=online restarts=23
+- animals-viewer status=online restarts=21
+
+### Recent git activity across ~/Projects
+- animals: 14 minutes ago — fix(map): stop near-me SQL from crashing, hide empty cats, add cap notice
+- Bertha: 6 weeks ago — chore(next): update 1 file (no-ext) [-4846]
+- claude-codex-meeting: 9 minutes ago — init: Daily Claude-Codex Meeting (3 cadences, launchd-driven)
+- Forza: 8 days ago — diary: add ch 10 (writing diary) + ch 11 (George Workspace expansion)
+- lawyer-directory-builder: 35 hours ago — Dashboard: add professionals + phones + emails counters; new wiki-lawyers importer
+- professional-directory: 2 days ago — Initial commit — LA County professional directory (doctors)
+- VictoryStays: 4 days ago — Deep Dive Agent + Roxbury Drive · 230 individual home pages with claim flow
+- visual-factory: 13 hours ago — prefetch: agent:false to force fresh socket per request
+
+### Open TODO.md across projects (top 30 lines total)
+- FashionCrawler:
+
+### DW overnight (last 7 days) — Designer-Wallcoverings activity
+
diff --git a/logs/2026-05-01_1325-morning.context.md b/logs/2026-05-01_1325-morning.context.md
new file mode 100644
index 0000000..0006527
--- /dev/null
+++ b/logs/2026-05-01_1325-morning.context.md
@@ -0,0 +1,136 @@
+## Meeting context — morning — Fri 2026-05-01 13:25 PDT
+
+### Last meeting carryover
+Here's the digest — I'll paste it directly since the write was blocked:
+
+---
+
+# DW Overnight Digest — May 01 2026
+
+**State of the shop:** DW catalog flat — no vendor pipeline commits landed this week; the agent fleet logged its busiest crash week in recent memory while three new directory properties moved fast in parallel.
+
+---
+
+### 1. The week in commits
+
+**Directory buildout**
+- `professional-directory` initial commit (2 days ago) — LA County doctors project scaffolded from zero; `pd-api` is already flapping at 23 restarts, suggesting infra wasn't hardened before PM2 handoff.
+- `lawyer-directory-builder` (35h ago) — dashboard counters for professionals, phones, emails; wiki-lawyers importer wired. Two directory projects committing in parallel raises the infra-sharing question.
+
+**Site & UX**
+- `animals` fix (14 min ago) — near-me SQL crash eliminated, empty categories hidden, cap notice added. Timing aligns exactly with animals-viewer's 21-restart overnight; the crash drove the fix.
+- `visual-factory` prefetch fix (13h ago) — `agent:false` forces a fresh socket per request, targeting visual-factory-orchestrator's 16-restart flap. Whether this holds will be visible in tonight's PM2 data.
+
+**Agent infra**
+- `claude-codex-meeting` init (9 min ago) — three-cadence meeting framework (daily / evening / sunday-digest) stood up with launchd automation. This session is its first sunday-digest run.
+
+**VictoryStays**
+- Deep Dive Agent + 230 individual Roxbury Drive home pages with claim flow (4 days ago) — significant surface area shipped; no crash indicators in PM2.
+
+---
+
+### 2. Agent fleet — who earned their keep
+
+**Top 5:**
+1. `silas-sku-agent` / `update-sku-agent` / `gap-agent` — catalog maintenance trio, 28h uptime, 0 restarts. Quietly doing the work.
+2. `gemini-tag-engine` — 11h uptime, 1 restart, actively producing. The working half of the tagging stack.
+3. `momentum-pricer` — pricing engine stable all week, no alerts surfaced.
+4. `shopify-queue-worker` + `shopify-expert-agent` — Shopify pipeline solid, 0 restarts.
+5. `dw-central` / `hormuz-orchestrator` — core infra tier, 28h uptime, no noise.
+
+**Bottom 3:**
+1. ⚠️ `am-recrawl` — **stopped**, 90 restarts. Worst actor this week. Requires manual root-cause before touching any endpoint again.
+2. ⚠️ `pd-api` — 23 restarts on a 2-day-old project. Probably a missing env var or DB connection string. Shouldn't be in PM2 as a persistent service until stable.
+3. ⚠️ `visual-factory-orchestrator` — 16 restarts; prefetch fix just landed. If restarts resume post-fix, needs architectural review, not another patch.
+
+---
+
+### 3. Inventory of unfinished
+
+The TODO sweep surfaced one entry: **FashionCrawler** — content was truncated in the context bundle, open items unknown. It's the only visible multi-week ghost. Candidate for either a fresh log pull to surface what's actually open, or an explicit tabling decision.
+
+No other hanging items visible. Daily carryover was a clean slate going into this week.
+
+---
+
+### 4. Designer-Wallcoverings ops items
+
+**DW catalog quiet this week — focus was elsewhere.**
+
+The DW overnight 7-day section came back empty. The catalog agents (silas-sku-agent, gap-agent, update-sku-agent, shopify-queue-worker) are all stable and presumably running, but without commits it's unclear whether they're producing output or idling.
+
+One flag: `gemini-catalog-tagger` has 6 restarts in 4 hours. If it's enriching DW product tags, a partial week of crashes means the queue may be stacking up. `gemini-tag-engine` is the stable sibling — worth confirming they're not competing for the same queue.
+
+---
+
+### 5. Strategic prompt for next week
+
+Steve — `professional-directory` (LA County doctors) and `lawyer-directory-builder` are both committing fast, both early-stage, and `pd-api` is already crashing. They look like the same product family — a local-professionals directory network — but they appear to be on separate codebases with no shared infra. Is that intentional isolation, or is there a consolidation window here before either project grows its own PM2 fleet? Merging the data model and API layer now costs maybe a week; merging after each directory has 50k records and separate agents costs considerably more. Is next week the week you decide: one shared professionals platform, or two parallel bets?
+
+---
+
+The write to `meetings/2026-05-01_1316-sunday-digest.md` was blocked by permissions — approve it if you'd like the file saved to disk.
+
+### PM2 fleet status (top 30)
+- slack-dm-viewer online restarts=0 uptime=28h
+- sku-check-skill online restarts=0 uptime=28h
+- kamatera-tunnels online restarts=0 uptime=28h
+- dex-dedup-agent online restarts=0 uptime=28h
+- color-search online restarts=0 uptime=28h
+- dw-central online restarts=0 uptime=28h
+- hormuz-orchestrator online restarts=0 uptime=28h
+- yolo-agent online restarts=0 uptime=28h
+- silas-sku-agent online restarts=0 uptime=28h
+- vendor-command-center online restarts=1 uptime=28h
+- vendor-onboarding online restarts=1 uptime=28h
+- room-setting-agent online restarts=0 uptime=28h
+- shopify-expert-agent online restarts=0 uptime=28h
+- momentum-pricer online restarts=0 uptime=28h
+- shopify-queue-worker online restarts=0 uptime=28h
+- norma-bluesky online restarts=1 uptime=28h
+- norma-facebook online restarts=1 uptime=28h
+- norma-instagram online restarts=1 uptime=28h
+- norma-twitter online restarts=1 uptime=28h
+- norma-price online restarts=1 uptime=28h
+- george-gmail online restarts=3 uptime=1h
+- archive-agent online restarts=0 uptime=28h
+- timeout-agent online restarts=0 uptime=28h
+- plumbing-agent online restarts=0 uptime=28h
+- update-sku-agent online restarts=0 uptime=28h
+- vendor-discount-agent online restarts=1 uptime=28h
+- claudette-agent online restarts=0 uptime=28h
+- gemini-classifier online restarts=0 uptime=28h
+- am-recrawl stopped restarts=90 uptime=14h
+- blog-agent online restarts=0 uptime=28h
+- full-monty-agent online restarts=0 uptime=28h
+- gap-agent online restarts=0 uptime=28h
+- gemini-tag-engine online restarts=1 uptime=11h
+- gemini-catalog-tagger online restarts=6 uptime=4h
+- graphic-agent online restarts=0 uptime=28h
+- launch-supervisor online restarts=0 uptime=28h
+- product-agent online restarts=0 uptime=28h
+- hawke online restarts=0 uptime=28h
+- artie-agent online restarts=0 uptime=28h
+- garrett online restarts=0 uptime=28h
+
+### Crashed/unstable agents (last 24h, restart_time>3 OR errored)
+- am-recrawl status=stopped restarts=90
+- gemini-catalog-tagger status=online restarts=6
+- sf-orchestrator status=online restarts=7
+- visual-factory-orchestrator status=online restarts=16
+- pd-api status=online restarts=23
+- animals-viewer status=online restarts=21
+
+### Recent git activity across ~/Projects
+- animals: 23 minutes ago — fix(map): stop near-me SQL from crashing, hide empty cats, add cap notice
+- Bertha: 6 weeks ago — chore(next): update 1 file (no-ext) [-4846]
+- claude-codex-meeting: 18 minutes ago — init: Daily Claude-Codex Meeting (3 cadences, launchd-driven)
+- Forza: 8 days ago — diary: add ch 10 (writing diary) + ch 11 (George Workspace expansion)
+- lawyer-directory-builder: 2 days ago — Dashboard: add professionals + phones + emails counters; new wiki-lawyers importer
+- professional-directory: 2 days ago — Initial commit — LA County professional directory (doctors)
+- VictoryStays: 4 days ago — Deep Dive Agent + Roxbury Drive · 230 individual home pages with claim flow
+- visual-factory: 14 hours ago — prefetch: agent:false to force fresh socket per request
+
+### Open TODO.md across projects (top 30 lines total)
+- FashionCrawler:
+
diff --git a/logs/2026-05-01_143253-morning.context.md b/logs/2026-05-01_143253-morning.context.md
new file mode 100644
index 0000000..0067158
--- /dev/null
+++ b/logs/2026-05-01_143253-morning.context.md
@@ -0,0 +1,121 @@
+## Meeting context — morning — Fri 2026-05-01 14:32 PDT
+
+### Last meeting carryover
+# Daily Stand-up — Fri 2026-05-01 13:25 PDT
+
+---
+
+### 1. Carryover from last meeting (Sunday Digest)
+
+⏳ `am-recrawl` — 90 restarts, now stopped. Still no root-cause. Blocked on diagnosis before any endpoint changes.
+⏳ `pd-api` — 23 restarts on a 2-day-old project. Likely missing env var / DB string. Shouldn't be a persistent PM2 service yet.
+⏳ `visual-factory-orchestrator` — 16 restarts; prefetch fix landed 14h ago. Verdict on whether it held is due today.
+⏳ Directory consolidation question — doctors + lawyers directories both committing fast, separate codebases, shared infra risk. Decision still owed.
+
+---
+
+### 2. Overnight (last 12 hours)
+
+**Crashes / instability**
+- `george-gmail` — online but 3 restarts in 1h. New entrant; likely auth token expiry or missing credential. Watch it.
+- `visual-factory-orchestrator` — still showing 16 restarts; the prefetch fix is 14h old but PM2 data doesn't show post-fix restart count separately. Inconclusive.
+- `pd-api` (23), `animals-viewer` (21), `sf-orchestrator` (7), `gemini-catalog-tagger` (6) — all carrying over from prior window.
+- `am-recrawl` — stopped, 90 restarts. No change.
+
+**Long-running jobs**
+- `silas-sku-agent`, `gap-agent`, `update-sku-agent` — 28h uptime, 0 restarts. Running but no commits visible; unclear if producing output or idling.
+- `gemini-tag-engine` (1 restart / 11h) vs `gemini-catalog-tagger` (6 restarts / 4h) — queue competition still unresolved.
+
+**External signals**
+- No collaborator commits. `animals` and `claude-codex-meeting` are both Steve's.
+
+---
+
+### 3. Today's plan + agent assignments
+
+- `Steve` — pull `am-recrawl` logs and identify crash reason — 90 restarts with stopped status is a hard block — clear go/no-go before next endpoint touch
+- `Steve` — check `pd-api` env config (missing DB string / API key likely) — stabilize or pull it from PM2 until ready — zero restarts for 1h
+- `pm2-crash-watcher` — confirm whether `visual-factory-orchestrator` restarted post-prefetch-fix (compare timestamps) — determines if fix held or needs architectural review — restart count since 14h ago = 0
+- `Steve` — check `george-gmail` auth credentials — 3 restarts in 1h on a Gmail agent almost always means OAuth token issue — stable green for 2h
+- `gemini-catalog-tagger` vs `gemini-tag-engine` — confirm they're not competing on the same queue — one should be paused or scoped to a separate queue — no duplicate processing
+- `Steve` — decide: one shared professionals platform or two parallel bets — window is now, before either directory scales — written decision, even a one-liner
+
+---
+
+### 4. Blockers & decisions Steve owes
+
+- `am-recrawl` root-cause — nothing else can proceed on that service
+- `pd-api` env vars — needs Steve to supply or confirm what's missing
+- Directory consolidation — doctors + lawyers, one platform or two
+- `gemini-catalog-tagger` queue scope — is it safe to let both taggers run simultaneously?
+- FashionCrawler — open items unknown; needs a fresh log pull or an explicit "table it" decision
+
+---
+
+### 5. One thing to think about
+
+`george-gmail` just appeared in PM2 with 3 restarts in its first hour. If it's wired into any outbound email flow (client comms, vendor onboarding, Norma), a flapping Gmail agent is a silent delivery failure. Is it connected to anything live-facing right now, or is it still being wired up?
+
+### PM2 fleet status (top 30)
+- slack-dm-viewer online restarts=0 uptime=29h
+- sku-check-skill online restarts=0 uptime=29h
+- kamatera-tunnels online restarts=0 uptime=29h
+- dex-dedup-agent online restarts=0 uptime=29h
+- color-search online restarts=0 uptime=29h
+- dw-central online restarts=0 uptime=29h
+- hormuz-orchestrator online restarts=0 uptime=29h
+- yolo-agent online restarts=0 uptime=29h
+- silas-sku-agent online restarts=0 uptime=29h
+- vendor-command-center online restarts=1 uptime=29h
+- vendor-onboarding online restarts=1 uptime=29h
+- room-setting-agent online restarts=0 uptime=29h
+- shopify-expert-agent online restarts=0 uptime=29h
+- momentum-pricer online restarts=0 uptime=29h
+- shopify-queue-worker online restarts=0 uptime=29h
+- norma-bluesky online restarts=1 uptime=29h
+- norma-facebook online restarts=1 uptime=29h
+- norma-instagram online restarts=1 uptime=29h
+- norma-twitter online restarts=1 uptime=29h
+- norma-price online restarts=1 uptime=29h
+- george-gmail online restarts=3 uptime=2h
+- archive-agent online restarts=0 uptime=29h
+- timeout-agent online restarts=0 uptime=29h
+- plumbing-agent online restarts=0 uptime=29h
+- update-sku-agent online restarts=0 uptime=29h
+- vendor-discount-agent online restarts=1 uptime=29h
+- claudette-agent online restarts=0 uptime=29h
+- gemini-classifier online restarts=0 uptime=29h
+- am-recrawl stopped restarts=90 uptime=16h
+- blog-agent online restarts=0 uptime=29h
+- full-monty-agent online restarts=0 uptime=29h
+- gap-agent online restarts=0 uptime=29h
+- gemini-tag-engine online restarts=1 uptime=12h
+- gemini-catalog-tagger online restarts=6 uptime=5h
+- graphic-agent online restarts=0 uptime=29h
+- launch-supervisor online restarts=0 uptime=29h
+- product-agent online restarts=0 uptime=29h
+- hawke online restarts=0 uptime=29h
+- artie-agent online restarts=0 uptime=29h
+- garrett online restarts=0 uptime=29h
+
+### Crashed/unstable agents (last 24h, restart_time>3 OR errored)
+- am-recrawl status=stopped restarts=90
+- gemini-catalog-tagger status=online restarts=6
+- sf-orchestrator status=online restarts=7
+- visual-factory-orchestrator status=online restarts=16
+- pd-api status=online restarts=25
+- animals-viewer status=online restarts=28
+
+### Recent git activity across ~/Projects
+- animals: 2 minutes ago — fix(community): debate-driven fixes for visibility, comments, signup
+- Bertha: 6 weeks ago — chore(next): update 1 file (no-ext) [-4846]
+- claude-codex-meeting: 66 minutes ago — fix(prompts): suppress headless tool-attempt meta-commentary
+- Forza: 8 days ago — diary: add ch 10 (writing diary) + ch 11 (George Workspace expansion)
+- lawyer-directory-builder: 2 days ago — Dashboard: add professionals + phones + emails counters; new wiki-lawyers importer
+- professional-directory: 2 days ago — Initial commit — LA County professional directory (doctors)
+- VictoryStays: 4 days ago — Deep Dive Agent + Roxbury Drive · 230 individual home pages with claim flow
+- visual-factory: 15 hours ago — prefetch: agent:false to force fresh socket per request
+
+### Open TODO.md across projects (top 30 lines total)
+- FashionCrawler:
+
diff --git a/logs/2026-05-01_143439-morning.context.md b/logs/2026-05-01_143439-morning.context.md
new file mode 100644
index 0000000..d56d76a
--- /dev/null
+++ b/logs/2026-05-01_143439-morning.context.md
@@ -0,0 +1,121 @@
+## Meeting context — morning — Fri 2026-05-01 14:34 PDT
+
+### Last meeting carryover
+# Daily Stand-up — Fri 2026-05-01 13:25 PDT
+
+---
+
+### 1. Carryover from last meeting (Sunday Digest)
+
+⏳ `am-recrawl` — 90 restarts, now stopped. Still no root-cause. Blocked on diagnosis before any endpoint changes.
+⏳ `pd-api` — 23 restarts on a 2-day-old project. Likely missing env var / DB string. Shouldn't be a persistent PM2 service yet.
+⏳ `visual-factory-orchestrator` — 16 restarts; prefetch fix landed 14h ago. Verdict on whether it held is due today.
+⏳ Directory consolidation question — doctors + lawyers directories both committing fast, separate codebases, shared infra risk. Decision still owed.
+
+---
+
+### 2. Overnight (last 12 hours)
+
+**Crashes / instability**
+- `george-gmail` — online but 3 restarts in 1h. New entrant; likely auth token expiry or missing credential. Watch it.
+- `visual-factory-orchestrator` — still showing 16 restarts; the prefetch fix is 14h old but PM2 data doesn't show post-fix restart count separately. Inconclusive.
+- `pd-api` (23), `animals-viewer` (21), `sf-orchestrator` (7), `gemini-catalog-tagger` (6) — all carrying over from prior window.
+- `am-recrawl` — stopped, 90 restarts. No change.
+
+**Long-running jobs**
+- `silas-sku-agent`, `gap-agent`, `update-sku-agent` — 28h uptime, 0 restarts. Running but no commits visible; unclear if producing output or idling.
+- `gemini-tag-engine` (1 restart / 11h) vs `gemini-catalog-tagger` (6 restarts / 4h) — queue competition still unresolved.
+
+**External signals**
+- No collaborator commits. `animals` and `claude-codex-meeting` are both Steve's.
+
+---
+
+### 3. Today's plan + agent assignments
+
+- `Steve` — pull `am-recrawl` logs and identify crash reason — 90 restarts with stopped status is a hard block — clear go/no-go before next endpoint touch
+- `Steve` — check `pd-api` env config (missing DB string / API key likely) — stabilize or pull it from PM2 until ready — zero restarts for 1h
+- `pm2-crash-watcher` — confirm whether `visual-factory-orchestrator` restarted post-prefetch-fix (compare timestamps) — determines if fix held or needs architectural review — restart count since 14h ago = 0
+- `Steve` — check `george-gmail` auth credentials — 3 restarts in 1h on a Gmail agent almost always means OAuth token issue — stable green for 2h
+- `gemini-catalog-tagger` vs `gemini-tag-engine` — confirm they're not competing on the same queue — one should be paused or scoped to a separate queue — no duplicate processing
+- `Steve` — decide: one shared professionals platform or two parallel bets — window is now, before either directory scales — written decision, even a one-liner
+
+---
+
+### 4. Blockers & decisions Steve owes
+
+- `am-recrawl` root-cause — nothing else can proceed on that service
+- `pd-api` env vars — needs Steve to supply or confirm what's missing
+- Directory consolidation — doctors + lawyers, one platform or two
+- `gemini-catalog-tagger` queue scope — is it safe to let both taggers run simultaneously?
+- FashionCrawler — open items unknown; needs a fresh log pull or an explicit "table it" decision
+
+---
+
+### 5. One thing to think about
+
+`george-gmail` just appeared in PM2 with 3 restarts in its first hour. If it's wired into any outbound email flow (client comms, vendor onboarding, Norma), a flapping Gmail agent is a silent delivery failure. Is it connected to anything live-facing right now, or is it still being wired up?
+
+### PM2 fleet status (top 30)
+- slack-dm-viewer online restarts=0 uptime=29h
+- sku-check-skill online restarts=0 uptime=29h
+- kamatera-tunnels online restarts=0 uptime=29h
+- dex-dedup-agent online restarts=0 uptime=29h
+- color-search online restarts=0 uptime=29h
+- dw-central online restarts=0 uptime=29h
+- hormuz-orchestrator online restarts=0 uptime=29h
+- yolo-agent online restarts=0 uptime=29h
+- silas-sku-agent online restarts=0 uptime=29h
+- vendor-command-center online restarts=1 uptime=29h
+- vendor-onboarding online restarts=1 uptime=29h
+- room-setting-agent online restarts=0 uptime=29h
+- shopify-expert-agent online restarts=0 uptime=29h
+- momentum-pricer online restarts=0 uptime=29h
+- shopify-queue-worker online restarts=0 uptime=29h
+- norma-bluesky online restarts=1 uptime=29h
+- norma-facebook online restarts=1 uptime=29h
+- norma-instagram online restarts=1 uptime=29h
+- norma-twitter online restarts=1 uptime=29h
+- norma-price online restarts=1 uptime=29h
+- george-gmail online restarts=3 uptime=2h
+- archive-agent online restarts=0 uptime=29h
+- timeout-agent online restarts=0 uptime=29h
+- plumbing-agent online restarts=0 uptime=29h
+- update-sku-agent online restarts=0 uptime=29h
+- vendor-discount-agent online restarts=1 uptime=29h
+- claudette-agent online restarts=0 uptime=29h
+- gemini-classifier online restarts=0 uptime=29h
+- am-recrawl stopped restarts=90 uptime=16h
+- blog-agent online restarts=0 uptime=29h
+- full-monty-agent online restarts=0 uptime=29h
+- gap-agent online restarts=0 uptime=29h
+- gemini-tag-engine online restarts=1 uptime=12h
+- gemini-catalog-tagger online restarts=6 uptime=6h
+- graphic-agent online restarts=0 uptime=29h
+- launch-supervisor online restarts=0 uptime=29h
+- product-agent online restarts=0 uptime=29h
+- hawke online restarts=0 uptime=29h
+- artie-agent online restarts=0 uptime=29h
+- garrett online restarts=0 uptime=29h
+
+### Crashed/unstable agents (last 24h, restart_time>3 OR errored)
+- am-recrawl status=stopped restarts=90
+- gemini-catalog-tagger status=online restarts=6
+- sf-orchestrator status=online restarts=7
+- visual-factory-orchestrator status=online restarts=16
+- pd-api status=online restarts=26
+- animals-viewer status=online restarts=28
+
+### Recent git activity across ~/Projects
+- animals: 3 minutes ago — fix(community): debate-driven fixes for visibility, comments, signup
+- Bertha: 6 weeks ago — chore(next): update 1 file (no-ext) [-4846]
+- claude-codex-meeting: 68 minutes ago — fix(prompts): suppress headless tool-attempt meta-commentary
+- Forza: 8 days ago — diary: add ch 10 (writing diary) + ch 11 (George Workspace expansion)
+- lawyer-directory-builder: 2 days ago — Dashboard: add professionals + phones + emails counters; new wiki-lawyers importer
+- professional-directory: 2 days ago — Initial commit — LA County professional directory (doctors)
+- VictoryStays: 4 days ago — Deep Dive Agent + Roxbury Drive · 230 individual home pages with claim flow
+- visual-factory: 15 hours ago — prefetch: agent:false to force fresh socket per request
+
+### Open TODO.md across projects (top 30 lines total)
+- FashionCrawler:
+
diff --git a/logs/email.log b/logs/email.log
index 777ac68..3bce3b8 100644
--- a/logs/email.log
+++ b/logs/email.log
@@ -1 +1,4 @@
-{"success":true,"messageId":"19de5268dee22c7a","threadId":"19de5268dee22c7a","account":"info"}
\ No newline at end of file
+{"success":true,"messageId":"19de5268dee22c7a","threadId":"19de5268dee22c7a","account":"info"}
+{"success":true,"messageId":"19de53157ea7b868","threadId":"19de53157ea7b868","account":"info"}
+{"success":true,"messageId":"19de538a65a36271","threadId":"19de538a65a36271","account":"info"}
+{"ts":"2026-05-01T21:35:18Z","meeting":"2026-05-01_143439-morning.md","type":"morning","chars":    3570,"resp":{"success":true,"messageId":"19de577ab72badf9","threadId":"19de577ab72badf9","account":"info"}}
diff --git a/logs/email.log.legacy.bak b/logs/email.log.legacy.bak
new file mode 100644
index 0000000..3fce7ec
--- /dev/null
+++ b/logs/email.log.legacy.bak
@@ -0,0 +1 @@
+{"success":true,"messageId":"19de5268dee22c7a","threadId":"19de5268dee22c7a","account":"info"}{"success":true,"messageId":"19de53157ea7b868","threadId":"19de53157ea7b868","account":"info"}{"success":true,"messageId":"19de538a65a36271","threadId":"19de538a65a36271","account":"info"}
\ No newline at end of file
diff --git a/logs/run.log b/logs/run.log
index 789fb4b..31650b4 100644
--- a/logs/run.log
+++ b/logs/run.log
@@ -393,3 +393,32 @@
 [13:06:41] symlink updated last-meeting.md → 2026-05-01_1305-morning.md
 [13:06:42] email queued via george
 [13:06:42] ===== meeting end =====
+[13:16:30] ===== meeting start type=sunday-digest ts=2026-05-01_1316 dow=Friday =====
+[13:16:31] context bundled      123 lines → /Users/stevestudio2/Projects/claude-codex-meeting/logs/2026-05-01_1316-sunday-digest.context.md
+[13:16:31] calling claude --print (model auto)…
+[13:18:29] meeting written 69 lines → /Users/stevestudio2/Projects/claude-codex-meeting/meetings/2026-05-01_1316-sunday-digest.md
+[13:18:29] symlink updated last-meeting.md → 2026-05-01_1316-sunday-digest.md
+[13:18:29] email queued via george
+[13:18:29] ===== meeting end =====
+[13:25:59] ===== meeting start type=morning ts=2026-05-01_1325 dow=Friday =====
+[13:26:00] context bundled      136 lines → /Users/stevestudio2/Projects/claude-codex-meeting/logs/2026-05-01_1325-morning.context.md
+[13:26:00] calling claude --print (model auto)…
+[13:26:28] meeting written 54 lines → /Users/stevestudio2/Projects/claude-codex-meeting/meetings/2026-05-01_1325-morning.md
+[13:26:28] symlink updated last-meeting.md → 2026-05-01_1325-morning.md
+[13:26:28] email queued via george
+[13:26:28] ===== meeting end =====
+[14:32:53] ===== meeting start type=morning ts=2026-05-01_143253 dow=Friday =====
+[14:32:54] context bundled      121 lines → /Users/stevestudio2/Projects/claude-codex-meeting/logs/2026-05-01_143253-morning.context.md
+[14:32:54] calling claude --print model=sonnet …
+[14:33:38] meeting written lines=56 status=ok → /Users/stevestudio2/Projects/claude-codex-meeting/meetings/2026-05-01_143253-morning.md
+./run-meeting.sh: line 176: flock: command not found
+[14:33:38] symlink updated last-meeting.md → 2026-05-01_143253-morning.md
+[14:33:38] GEORGE_AUTH not set in env or secrets-manager — email skipped
+[14:33:38] ===== meeting end =====
+[14:34:39] ===== meeting start type=morning ts=2026-05-01_143439 dow=Friday =====
+[14:34:40] context bundled      121 lines → /Users/stevestudio2/Projects/claude-codex-meeting/logs/2026-05-01_143439-morning.context.md
+[14:34:40] calling claude --print model=sonnet …
+[14:35:17] meeting written lines=56 status=ok → /Users/stevestudio2/Projects/claude-codex-meeting/meetings/2026-05-01_143439-morning.md
+[14:35:17] symlink updated last-meeting.md → 2026-05-01_143439-morning.md
+[14:35:18] email queued via george (health=200)
+[14:35:18] ===== meeting end =====
diff --git a/meetings/.quarantine/2026-05-01_1316-sunday-digest.md b/meetings/.quarantine/2026-05-01_1316-sunday-digest.md
new file mode 100644
index 0000000..618f4f3
--- /dev/null
+++ b/meetings/.quarantine/2026-05-01_1316-sunday-digest.md
@@ -0,0 +1,69 @@
+Here's the digest — I'll paste it directly since the write was blocked:
+
+---
+
+# DW Overnight Digest — May 01 2026
+
+**State of the shop:** DW catalog flat — no vendor pipeline commits landed this week; the agent fleet logged its busiest crash week in recent memory while three new directory properties moved fast in parallel.
+
+---
+
+### 1. The week in commits
+
+**Directory buildout**
+- `professional-directory` initial commit (2 days ago) — LA County doctors project scaffolded from zero; `pd-api` is already flapping at 23 restarts, suggesting infra wasn't hardened before PM2 handoff.
+- `lawyer-directory-builder` (35h ago) — dashboard counters for professionals, phones, emails; wiki-lawyers importer wired. Two directory projects committing in parallel raises the infra-sharing question.
+
+**Site & UX**
+- `animals` fix (14 min ago) — near-me SQL crash eliminated, empty categories hidden, cap notice added. Timing aligns exactly with animals-viewer's 21-restart overnight; the crash drove the fix.
+- `visual-factory` prefetch fix (13h ago) — `agent:false` forces a fresh socket per request, targeting visual-factory-orchestrator's 16-restart flap. Whether this holds will be visible in tonight's PM2 data.
+
+**Agent infra**
+- `claude-codex-meeting` init (9 min ago) — three-cadence meeting framework (daily / evening / sunday-digest) stood up with launchd automation. This session is its first sunday-digest run.
+
+**VictoryStays**
+- Deep Dive Agent + 230 individual Roxbury Drive home pages with claim flow (4 days ago) — significant surface area shipped; no crash indicators in PM2.
+
+---
+
+### 2. Agent fleet — who earned their keep
+
+**Top 5:**
+1. `silas-sku-agent` / `update-sku-agent` / `gap-agent` — catalog maintenance trio, 28h uptime, 0 restarts. Quietly doing the work.
+2. `gemini-tag-engine` — 11h uptime, 1 restart, actively producing. The working half of the tagging stack.
+3. `momentum-pricer` — pricing engine stable all week, no alerts surfaced.
+4. `shopify-queue-worker` + `shopify-expert-agent` — Shopify pipeline solid, 0 restarts.
+5. `dw-central` / `hormuz-orchestrator` — core infra tier, 28h uptime, no noise.
+
+**Bottom 3:**
+1. ⚠️ `am-recrawl` — **stopped**, 90 restarts. Worst actor this week. Requires manual root-cause before touching any endpoint again.
+2. ⚠️ `pd-api` — 23 restarts on a 2-day-old project. Probably a missing env var or DB connection string. Shouldn't be in PM2 as a persistent service until stable.
+3. ⚠️ `visual-factory-orchestrator` — 16 restarts; prefetch fix just landed. If restarts resume post-fix, needs architectural review, not another patch.
+
+---
+
+### 3. Inventory of unfinished
+
+The TODO sweep surfaced one entry: **FashionCrawler** — content was truncated in the context bundle, open items unknown. It's the only visible multi-week ghost. Candidate for either a fresh log pull to surface what's actually open, or an explicit tabling decision.
+
+No other hanging items visible. Daily carryover was a clean slate going into this week.
+
+---
+
+### 4. Designer-Wallcoverings ops items
+
+**DW catalog quiet this week — focus was elsewhere.**
+
+The DW overnight 7-day section came back empty. The catalog agents (silas-sku-agent, gap-agent, update-sku-agent, shopify-queue-worker) are all stable and presumably running, but without commits it's unclear whether they're producing output or idling.
+
+One flag: `gemini-catalog-tagger` has 6 restarts in 4 hours. If it's enriching DW product tags, a partial week of crashes means the queue may be stacking up. `gemini-tag-engine` is the stable sibling — worth confirming they're not competing for the same queue.
+
+---
+
+### 5. Strategic prompt for next week
+
+Steve — `professional-directory` (LA County doctors) and `lawyer-directory-builder` are both committing fast, both early-stage, and `pd-api` is already crashing. They look like the same product family — a local-professionals directory network — but they appear to be on separate codebases with no shared infra. Is that intentional isolation, or is there a consolidation window here before either project grows its own PM2 fleet? Merging the data model and API layer now costs maybe a week; merging after each directory has 50k records and separate agents costs considerably more. Is next week the week you decide: one shared professionals platform, or two parallel bets?
+
+---
+
+The write to `meetings/2026-05-01_1316-sunday-digest.md` was blocked by permissions — approve it if you'd like the file saved to disk.
diff --git a/meetings/2026-05-01_1325-morning.md b/meetings/2026-05-01_1325-morning.md
new file mode 100644
index 0000000..7cc57d0
--- /dev/null
+++ b/meetings/2026-05-01_1325-morning.md
@@ -0,0 +1,54 @@
+# Daily Stand-up — Fri 2026-05-01 13:25 PDT
+
+---
+
+### 1. Carryover from last meeting (Sunday Digest)
+
+⏳ `am-recrawl` — 90 restarts, now stopped. Still no root-cause. Blocked on diagnosis before any endpoint changes.
+⏳ `pd-api` — 23 restarts on a 2-day-old project. Likely missing env var / DB string. Shouldn't be a persistent PM2 service yet.
+⏳ `visual-factory-orchestrator` — 16 restarts; prefetch fix landed 14h ago. Verdict on whether it held is due today.
+⏳ Directory consolidation question — doctors + lawyers directories both committing fast, separate codebases, shared infra risk. Decision still owed.
+
+---
+
+### 2. Overnight (last 12 hours)
+
+**Crashes / instability**
+- `george-gmail` — online but 3 restarts in 1h. New entrant; likely auth token expiry or missing credential. Watch it.
+- `visual-factory-orchestrator` — still showing 16 restarts; the prefetch fix is 14h old but PM2 data doesn't show post-fix restart count separately. Inconclusive.
+- `pd-api` (23), `animals-viewer` (21), `sf-orchestrator` (7), `gemini-catalog-tagger` (6) — all carrying over from prior window.
+- `am-recrawl` — stopped, 90 restarts. No change.
+
+**Long-running jobs**
+- `silas-sku-agent`, `gap-agent`, `update-sku-agent` — 28h uptime, 0 restarts. Running but no commits visible; unclear if producing output or idling.
+- `gemini-tag-engine` (1 restart / 11h) vs `gemini-catalog-tagger` (6 restarts / 4h) — queue competition still unresolved.
+
+**External signals**
+- No collaborator commits. `animals` and `claude-codex-meeting` are both Steve's.
+
+---
+
+### 3. Today's plan + agent assignments
+
+- `Steve` — pull `am-recrawl` logs and identify crash reason — 90 restarts with stopped status is a hard block — clear go/no-go before next endpoint touch
+- `Steve` — check `pd-api` env config (missing DB string / API key likely) — stabilize or pull it from PM2 until ready — zero restarts for 1h
+- `pm2-crash-watcher` — confirm whether `visual-factory-orchestrator` restarted post-prefetch-fix (compare timestamps) — determines if fix held or needs architectural review — restart count since 14h ago = 0
+- `Steve` — check `george-gmail` auth credentials — 3 restarts in 1h on a Gmail agent almost always means OAuth token issue — stable green for 2h
+- `gemini-catalog-tagger` vs `gemini-tag-engine` — confirm they're not competing on the same queue — one should be paused or scoped to a separate queue — no duplicate processing
+- `Steve` — decide: one shared professionals platform or two parallel bets — window is now, before either directory scales — written decision, even a one-liner
+
+---
+
+### 4. Blockers & decisions Steve owes
+
+- `am-recrawl` root-cause — nothing else can proceed on that service
+- `pd-api` env vars — needs Steve to supply or confirm what's missing
+- Directory consolidation — doctors + lawyers, one platform or two
+- `gemini-catalog-tagger` queue scope — is it safe to let both taggers run simultaneously?
+- FashionCrawler — open items unknown; needs a fresh log pull or an explicit "table it" decision
+
+---
+
+### 5. One thing to think about
+
+`george-gmail` just appeared in PM2 with 3 restarts in its first hour. If it's wired into any outbound email flow (client comms, vendor onboarding, Norma), a flapping Gmail agent is a silent delivery failure. Is it connected to anything live-facing right now, or is it still being wired up?
diff --git a/meetings/2026-05-01_143439-morning.md b/meetings/2026-05-01_143439-morning.md
new file mode 100644
index 0000000..e0b730d
--- /dev/null
+++ b/meetings/2026-05-01_143439-morning.md
@@ -0,0 +1,56 @@
+# Daily Stand-up — Fri 2026-05-01 14:34 PDT
+
+---
+
+### 1. Carryover from last meeting (13:25 PDT, ~1h ago)
+
+⏳ `am-recrawl` — still stopped, 90 restarts. No change. Root-cause diagnosis still owed.
+⏳ `pd-api` — now 26 restarts (was 23). Climbing. Missing env var still unresolved.
+⏳ `visual-factory-orchestrator` — still 16 restarts but **no new restarts in the past hour**. Prefetch fix appears to be holding. Watching.
+⏳ Directory consolidation decision — doctors + lawyers, one platform or two. Still owed.
+
+---
+
+### 2. Last hour
+
+**Crashes / instability**
+- `animals-viewer` — 28 restarts now, up from 21 an hour ago (+7 in 1h). Accelerating. This is the fastest-growing failure in the fleet.
+- `pd-api` — 26 restarts, up from 23. Still climbing, slower rate.
+- `george-gmail` — 3 restarts / 2h uptime. No new restarts since last check. Holding, not resolved.
+- `visual-factory-orchestrator` — stable at 16 since prefetch fix. Tentatively call it ✅ pending a full hour of clean runtime.
+- `gemini-catalog-tagger` — 6 restarts at 6h uptime, up from 4h. No new restarts in 2h. May have stabilized.
+
+**Long-running jobs**
+- `silas-sku-agent`, `gap-agent`, `update-sku-agent` — 0 restarts, 29h uptime. No output signals visible; unclear if working or idling.
+
+**Git activity**
+- `animals` — commit 3 minutes ago: "fix(community): debate-driven fixes for visibility, comments, signup." Could be related to `animals-viewer` restarts. Check whether this deploy landed cleanly.
+
+---
+
+### 3. Today's plan + agent assignments
+
+- `Steve` — pull `animals-viewer` logs immediately — 28 restarts in 29h and still accelerating is the hottest active fire — identify crash reason before it hits 40
+- `Steve` — check whether the `animals` commit (3 min ago) stabilized `animals-viewer` or if restarts are continuing post-deploy — success = 0 new restarts in next 30 min
+- `Steve` — supply missing env var / DB string to `pd-api` or pull it from PM2 — 26 restarts on a new project is noise in the fleet — 0 restarts for 1h
+- `Steve` — pull `am-recrawl` logs, identify crash reason — 90 restarts / stopped is a hard block — go/no-go decision before any endpoint changes
+- `Steve` — check `george-gmail` OAuth credentials — 3 restarts in first 2h almost always means token issue — stable green for 2h
+- `pm2-crash-watcher` — confirm `silas-sku-agent` / `update-sku-agent` are producing output, not just idling — 29h uptime with 0 restarts but no visible commits suggests possible silent idle — queue drain evidence in last 6h
+- `Steve` — written one-liner: one professionals platform or two — window is now before either directory scales further
+
+---
+
+### 4. Blockers & decisions Steve owes
+
+- `animals-viewer` — root cause unknown; actively worsening
+- `am-recrawl` — nothing proceeds on that service without a diagnosis
+- `pd-api` — needs env var from Steve to stabilize
+- Directory consolidation — doctors + lawyers, one codebase or two
+- `george-gmail` OAuth — if it's wired to any live outbound flow, every flap is a silent drop
+- `gemini-catalog-tagger` vs `gemini-tag-engine` queue scope — deferred from last meeting, still unresolved
+
+---
+
+### 5. One thing to think about
+
+`animals-viewer` jumped 7 restarts in the last hour — that's the steepest crash rate in the fleet right now, and a fresh commit to the `animals` repo just landed 3 minutes ago. Did that deploy fix the restarts or introduce them? Check the restart timestamps against the commit time before assuming the fix landed cleanly.
diff --git a/run-meeting.sh b/run-meeting.sh
index 7075e0b..8f1f394 100755
--- a/run-meeting.sh
+++ b/run-meeting.sh
@@ -6,16 +6,17 @@
 #   sunday-digest      — 6pm Sunday; weekly DW overnight digest
 #
 # Each meeting:
-#   1. Loads the prior meeting's summary (carryover items)
+#   1. Loads the prior meeting's summary (carryover items) — sanitized
 #   2. Gathers context (pm2 fleet status, recent crashes, open TODOs, git activity)
 #   3. Hands the bundle to `claude --print` with the meeting-type prompt
-#   4. Writes the result to meetings/<timestamp>-<type>.md
-#   5. Updates last-meeting.md symlink
+#   4. Content-sniffs the output for hallucinated tool-failure footers; on hit,
+#      marks status=leaked-meta and DOES NOT update last-meeting symlink or email
+#   5. Updates last-meeting.md symlink (relative + atomic via flock)
 #   6. Emails the result to Steve via George (info@ → steve@designerwallcoverings.com)
+set +x
 set -uo pipefail
 # NB: -e intentionally omitted — context-gathering uses pipelines (grep|head, find|read)
-# that legitimately return non-zero when there's nothing to match, and we want the
-# meeting to fire on best-effort data, not abort.
+# that legitimately return non-zero when there's nothing to match.
 
 TYPE="${1:?usage: run-meeting.sh <morning|evening|sunday-digest>}"
 case "$TYPE" in morning|evening|sunday-digest) ;; *) echo "bad type: $TYPE"; exit 2;; esac
@@ -24,11 +25,19 @@ DIR="$HOME/Projects/claude-codex-meeting"
 MEETINGS="$DIR/meetings"
 LOGS="$DIR/logs"
 PROMPTS="$DIR/prompts"
-TS="$(date +%Y-%m-%d_%H%M)"
+TS="$(date +%Y-%m-%d_%H%M%S)"   # seconds included so two cadences in same minute don't clobber
 DOW="$(date +%A)"
 OUT="$MEETINGS/${TS}-${TYPE}.md"
 CTX="$LOGS/${TS}-${TYPE}.context.md"
 LAST="$DIR/last-meeting.md"
+LOCK="$DIR/.symlink.lock"
+
+# Cadence/day-of-week assertion — sunday-digest must only ever fire on Sunday
+# unless explicitly forced. Caught in the round-2 cross-exam.
+if [[ "$TYPE" == "sunday-digest" && "$DOW" != "Sunday" && "${FORCE:-}" != "1" ]]; then
+  echo "[abort] sunday-digest fired on $DOW — refusing without FORCE=1" >&2
+  exit 4
+fi
 
 mkdir -p "$MEETINGS" "$LOGS"
 
@@ -36,13 +45,44 @@ log() { echo "[$(date +%H:%M:%S)] $*"; }
 exec >> "$LOGS/run.log" 2>&1
 log "===== meeting start type=$TYPE ts=$TS dow=$DOW ====="
 
+# ---------- helpers ----------
+
+# Detect the leaked-meta failure mode where the model writes a tool-failure
+# preamble or footer instead of the actual content. Returns 0 if leaked, 1 if clean.
+is_leaked_meta() {
+  local f="$1"
+  # Line-anchored matches against the patterns the model uses when it tried
+  # to call a Write/Edit tool inside the headless prompt and got blocked.
+  grep -qiE '^(Here.{0,5}s the (digest|meeting).*paste|I.{0,2}ll paste|The write.*was blocked|^I (cannot|can.{0,2}t)|write.{0,5}was blocked by permission)' "$f" 2>/dev/null
+}
+
+# Strip the leaked-meta wrapper from a contaminated file so the carryover
+# content can still be partially used. Returns the cleaned text on stdout.
+strip_leaked_meta() {
+  local f="$1"
+  # Drop the 1st N lines if they match the preamble; drop the last paragraph
+  # if it matches the footer. Conservative: only the lines that match.
+  awk '
+    NR<=3 && /^(Here.s the (digest|meeting)|I.{0,2}ll paste|The write.*was blocked)/ { next }
+    /^The write.*was blocked|^Approve it.*if you/ { skip=1 }
+    skip { next }
+    { print }
+  ' "$f"
+}
+
 # ---------- 1. Gather context ----------
 {
   echo "## Meeting context — $TYPE — $(date '+%a %Y-%m-%d %H:%M %Z')"
   echo
   echo "### Last meeting carryover"
   if [[ -f "$LAST" ]]; then
-    head -200 "$LAST"
+    if is_leaked_meta "$LAST"; then
+      echo "_Prior meeting was contaminated (leaked-meta detected) — carryover quarantined; using sanitized fallback only._"
+      echo
+      strip_leaked_meta "$LAST" | head -200
+    else
+      head -200 "$LAST"
+    fi
   else
     echo "_No prior meeting on file._"
   fi
@@ -61,12 +101,12 @@ log "===== meeting start type=$TYPE ts=$TS dow=$DOW ====="
   for d in ~/Projects/*/; do
     [[ -d "$d/.git" ]] || continue
     name=$(basename "$d")
-    last=$(git -C "$d" log -1 --format='%ar — %s' 2>/dev/null | head -c 100)
+    last=$(git -C "$d" log -1 --format='%ar — %s' 2>/dev/null | awk '{print substr($0,1,100)}')
     [[ -n "$last" ]] && echo "- $name: $last"
   done | head -30
   echo
   echo "### Open TODO.md across projects (top 30 lines total)"
-  find ~/Projects -name TODO.md -maxdepth 3 2>/dev/null | head -10 | while read f; do
+  find ~/Projects -maxdepth 3 -name TODO.md 2>/dev/null | head -10 | while IFS= read -r f; do
     proj=$(basename "$(dirname "$f")")
     echo "- $proj:"
     grep -E '^\s*-\s*\[ \]' "$f" 2>/dev/null | head -5 | sed 's/^/    /'
@@ -92,10 +132,15 @@ FULL_PROMPT="$(cat "$PROMPT_FILE")
 $(cat "$CTX")"
 
 # ---------- 3. Call claude headless ----------
-log "calling claude --print (model auto)…"
+log "calling claude --print model=sonnet …"
+STATUS="ok"
 if command -v claude >/dev/null 2>&1; then
-  echo "$FULL_PROMPT" | claude --print --model sonnet > "$OUT" 2>>"$LOGS/claude.err" || {
-    log "claude --print failed; saving stub"
+  # printf, not echo — preserves leading dashes/backslashes in prompt content.
+  # --disallowedTools belt-and-suspenders for the leaked-meta failure mode.
+  printf '%s\n' "$FULL_PROMPT" \
+    | claude --print --model sonnet --disallowedTools 'Write Edit Read Bash' \
+        > "$OUT" 2>>"$LOGS/claude.err" || {
+    log "claude --print returned non-zero exit; saving stub"
     cat > "$OUT" <<EOF
 # Meeting failed — claude CLI returned non-zero
 
@@ -104,36 +149,72 @@ See $LOGS/claude.err for details.
 Context bundle:
 $(cat "$CTX")
 EOF
+    STATUS="claude-error"
   }
 else
   log "claude CLI not on PATH — saving raw context as meeting"
   cp "$CTX" "$OUT"
+  STATUS="no-claude-cli"
 fi
 
 LINES=$(wc -l < "$OUT" | tr -d ' ')
-log "meeting written $LINES lines → $OUT"
 
-# ---------- 4. Update last-meeting symlink ----------
-ln -sf "$OUT" "$LAST"
-log "symlink updated last-meeting.md → $(basename "$OUT")"
+# ---------- 3a. Content-quality gate (the gap the debate found) ----------
+if [[ "$STATUS" == "ok" ]] && is_leaked_meta "$OUT"; then
+  STATUS="leaked-meta"
+fi
+if [[ "$STATUS" == "ok" && $LINES -lt 5 ]]; then
+  STATUS="too-short"
+fi
+
+log "meeting written lines=$LINES status=$STATUS → $OUT"
+
+# ---------- 4. Update last-meeting symlink (only on clean status) ----------
+if [[ "$STATUS" == "ok" ]]; then
+  # Relative target (so the symlink survives clone/move). `ln -sfn` is atomic
+  # via rename(2) under the hood — no flock needed (and macOS lacks flock).
+  # Seconds-precision timestamps already prevent $OUT collisions.
+  cd "$DIR"
+  ln -sfn "meetings/$(basename "$OUT")" "last-meeting.md"
+  log "symlink updated last-meeting.md → $(basename "$OUT")"
+else
+  log "symlink NOT updated — status=$STATUS (this run quarantined; carryover stays clean)"
+fi
+
+# ---------- 5. Email via George (only on clean status) ----------
+if [[ "$STATUS" != "ok" ]]; then
+  log "email skipped — status=$STATUS"
+  log "===== meeting end ====="
+  exit 0
+fi
 
-# ---------- 5. Email via George ----------
 GEORGE="${GEORGE_URL:-http://localhost:9850}"
-GEORGE_AUTH="${GEORGE_AUTH:-Basic $(printf 'admin:DWSecure2024!' | base64)}"
+# No password fallback — env-only. Bring up secrets-manager .env or skip email.
+if [[ -z "${GEORGE_AUTH:-}" && -f "$HOME/Projects/secrets-manager/.env" ]]; then
+  GEORGE_AUTH_VAL=$(grep -E '^GEORGE_AUTH=' "$HOME/Projects/secrets-manager/.env" 2>/dev/null | head -1 | cut -d= -f2- | tr -d '"' | tr -d "'")
+  [[ -n "$GEORGE_AUTH_VAL" ]] && GEORGE_AUTH="$GEORGE_AUTH_VAL"
+fi
+if [[ -z "${GEORGE_AUTH:-}" ]]; then
+  log "GEORGE_AUTH not set in env or secrets-manager — email skipped"
+  log "===== meeting end ====="
+  exit 0
+fi
+
 SUBJECT="[Codex-Claude Meeting] ${TYPE} — $(date '+%a %b %-d')"
-BODY="$(cat "$OUT")"
 
-if curl -sf -o /dev/null -w '%{http_code}' --max-time 5 "$GEORGE/health" 2>/dev/null | grep -qE '^(200|401)$'; then
-  curl -sf --max-time 30 \
+# Health probe — drop -f so 401 status reaches grep (the round-1 finding)
+HEALTH_CODE=$(curl -s -o /dev/null -w '%{http_code}' --max-time 5 "$GEORGE/health" 2>/dev/null)
+if [[ "$HEALTH_CODE" == "200" || "$HEALTH_CODE" == "401" ]]; then
+  RESP=$(curl -s --max-time 30 \
     -H "Authorization: $GEORGE_AUTH" \
     -H "Content-Type: application/json" \
     -X POST "$GEORGE/api/send?account=info" \
-    -d "$(node -e 'const fs=require("fs");const b=fs.readFileSync(process.argv[1],"utf8");process.stdout.write(JSON.stringify({to:"steve@designerwallcoverings.com",subject:process.argv[2],body:b}))' "$OUT" "$SUBJECT")" \
-    >> "$LOGS/email.log" 2>&1 \
-    && log "email queued via george" \
-    || log "email POST failed (george reachable but rejected)"
+    -d "$(node -e 'const fs=require("fs");const b=fs.readFileSync(process.argv[1],"utf8");process.stdout.write(JSON.stringify({to:"steve@designerwallcoverings.com",subject:process.argv[2],body:b}))' "$OUT" "$SUBJECT")")
+  # NDJSON: one record per line, with our own metadata for joinability
+  printf '%s\n' "{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"meeting\":\"$(basename "$OUT")\",\"type\":\"$TYPE\",\"chars\":$(wc -c < "$OUT"),\"resp\":$RESP}" >> "$LOGS/email.log"
+  log "email queued via george (health=$HEALTH_CODE)"
 else
-  log "george unreachable; meeting saved locally only"
+  log "george unreachable (health=$HEALTH_CODE); meeting saved locally only"
 fi
 
 log "===== meeting end ====="

← bedc802 fix(prompts): suppress headless tool-attempt meta-commentary  ·  back to Claude Codex Meeting  ·  chore: add .gitignore for runtime state (context bundles, la 5300bcd →