Dw Pitch Followup

repo: ~/Projects/dw-pitch-followup · 85 commits · 0 in last 24h, 1 in last 7d · █

Search the build

85 commits indexed

  1. 3828ac0 2026-09-25 refresh.sh: retry build-lists up to 3x on transient Claris ID/Cognito 'Network error' FATAL (TK-12258)
  2. 1989be5 2026-09-17 auto-data-snapshot: 2026-09-17T20:05:20 (1 data files) — data/suppress.json
  3. b5f1281 2026-09-15 security: add rel=noopener noreferrer to target=_blank links (yoloforever cycle 3)
  4. 5f4bb6e 2026-08-19 auto-data-snapshot: 2026-08-19T20:02:37 (1 data files) — data/suppress.json
  5. f8e1a7f 2026-08-18 refresh.sh: network-readiness guard before Claris auth — kills the RunAtLoad boot-race FATAL (Cody, yoloforever c4)
  6. 9f1d378 2026-08-17 auto-data-snapshot: 2026-08-17T20:02:38 (1 data files) — data/suppress.json
  7. 30bfd4f 2026-08-17 Record pitch-site Basic-Auth rotation to fleet-standard cred
  8. 32ac85c 2026-08-06 chore: v0.6.0 (session close) — catch-all route, Gmail correspondence table, 2AM rebuild fix, plist-lint hook
  9. e26fbb5 2026-08-06 Pitch drawer: render all Gmail correspondence as a table
  10. 705c715 2026-08-06 Add repo-local pre-commit: lint staged launchd/*.plist
  11. 264deba 2026-08-06 Fix pitch-rebuild launchd: valid plist + once-daily 2:00 AM schedule
  12. fc4911d 2026-08-06 Add catch-all: unknown non-api GETs redirect to / instead of raw Cannot GET 404
  13. 61ac5f6 2026-07-31 auto-save: 2026-07-31T20:00:42 (1 files) — data/suppress.json
  14. 04dc7da 2026-07-30 chore: lint ✓ + refactor ✓ (both clean, no code changes), v0.4.1 → v0.5.0 (session close)
  15. b50e31f 2026-07-30 pitch: package.json description now reflects reality — notes write path + /api/send (with suppression, 30-day, external-send token, ALLOW_TUNNEL_SEND guards); drop stale 'No sends'
  16. 56a35bd 2026-07-30 pitch: enable Send-now over the public tunnel via ALLOW_TUNNEL_SEND flag (Steve-approved) + Send button now shows 'send cancelled' so a dismissed confirm never looks dead
  17. 6330e75 2026-07-30 pitch: signpost 9768 (own listen port) vs 9850 (GEORGE client URL) — prevent the misread; keep PORT hardcoded to dodge pm2 stale-env
  18. 1ffa37a 2026-07-30 pitch: 30-day already-emailed guard now shows date AND time (server + confirm dialog) — completes the date+time-on-all-emails pass
  19. d3bd7eb 2026-07-30 pitch: ✓ emailed card chip now stamps date AND time (fmtWhen), matching the send panel + admin-card rule
  20. dcb29c4 2026-07-15 chore: lint, refactor (dedup repaint per unique email), v0.4.1 (session close)
  21. 229cd17 2026-07-15 fix(notes): FileMaker note-save silently no-op'd — write rep-1 bare key + read-back verify
  22. 109d6a3 2026-07-15 Make invoice # on the note chip + notes editor clickable — opens the invoice in FileMaker Pro via fmp:// GotoInvoice
  23. a923a04 2026-07-15 fix: ✓ emailed date chip appears immediately after send — repaint live cards by DOM lookup (active.card was detached after board re-renders), update SENT_IDX in memory for same-client cards in other lists, and refresh sent-index on tab focus for cross-device visibility
  24. 177117e 2026-07-15 Show invoice # + current internal note on every pitch card — batched FM read (50/query, 10-min cache), chip updates live on save
  25. 58c847e 2026-07-15 Add Internal-notes editor to pitch cards — 🗒 Notes button next to Done reads/writes FileMaker Invoice::Internal notes with dated entries
  26. e35cf91 2026-07-15 auto-save: 2026-07-15T10:35:56 (2 files) — server.js lib/fm-notes.js
  27. e90255c 2026-07-15 pitch: scheduled refresh now also pre-triages the whole board (build-lists → pretriage), so every card is Follow-up scored
  28. 5e218be 2026-07-15 pitch: Follow up? YES/NO chip on every card + per-column ⚡ Triage (batch, cached)
  29. 8e921dc 2026-07-15 pitch: auto follow-up triage — reads the email thread → Follow up? YES/NO + notes (delays, deadlines, status)
  30. e039b5a 2026-07-15 pitch: click any email in the history to expand its full body
  31. 8f32c4b 2026-07-15 pitch: add 3x/day launchd rebuild so the board never goes stale (bootstrap = Steve paste)
  32. e592d47 2026-07-15 pitch: email history collapsed by default, lazy-loads on expand (George search only fires when opened)
  33. a4bc2e8 2026-07-15 pitch: Details drawer shows full email history with each client
  34. 71574cf 2026-07-14 5x: 2 clean sweeps (7/7 six-way + 51 controls, 0 defects) after card/UX + George + FM batch
  35. 9aa4cdc 2026-07-14 pitch: letter panel shows product thumbnails + DW product-page links
  36. c6994a4 2026-07-14 pitch: list2 letter follows up on the specific QUOTE (number, total, items) not generic samples
  37. f9b6323 2026-07-14 pitch: Sent log is now LIVE — merge Gmail Sent (recipient-enriched) with the tool log
  38. 6c560f3 2026-07-14 pitch: FIX critical George 401 — resolve GEORGE_AUTH from secrets master (restores sends + threading + last-corr)
  39. c6d5609 2026-07-14 pitch: card/UX batch — dismiss-completed, park vendor memos, quote/order label fix, FM deep-links, live sent-index, expandable columns
  40. d4a8d30 2026-07-14 auto-save: 2026-07-14T11:00:40 (1 files) — public/index.html
  41. a59c63b 2026-07-14 pitch: redefine "Invoiced · No Order" list as real quotes never booked (totals + details)
  42. 395d98e 2026-07-13 chore: lint (esc XSS autofix + enrich-disco psql guard), refactor, v0.4.0 (session close)
  43. 4c40379 2026-07-13 auto-save: 2026-07-13T12:24:56 (1 files) — public/index.html
  44. 0b34230 2026-07-13 auto-save: 2026-07-13T11:54:48 (2 files) — public/index.html scripts/enrich-disco.js
  45. a22a58a 2026-07-13 auto-save: 2026-07-13T11:24:39 (2 files) — public/index.html scripts/build-lists.js
  46. 93dde31 2026-07-12 chore: v0.3.0 (session close — public tunnel + auth hardening: lockout, socket-guard, cred rotation, headers)
  47. 02b62f2 2026-07-12 yolo contrarian-gate fixes: socket-anchored /api/send guard (#1) + suppress audit log (#2)
  48. 211aef3 2026-07-12 yolo: baseline security headers (nosniff, frame-DENY, no-referrer) on public endpoint — closes contrarian 'no helmet' gap
  49. 09bfb88 2026-07-12 contrarian FIX FIRST #3: rotate public cred off shared DW2024! via app-local .env (envLocal reader)
  50. 577f14f 2026-07-12 contrarian FIX FIRST #2: per-IP brute-force lockout on public Basic Auth (10 fails/15m → 429)
  51. cf2ad96 2026-07-12 contrarian FIX FIRST #1: block /api/send for tunnel-origin requests (loopback-only mail send)
  52. 10b262d 2026-07-12 5x: REPORT.md — 2 sweeps, app clean, M3 networkidle proven CDN artifact
  53. d29d6ef 2026-07-12 5x sweep 1: add auth-exempt /favicon.ico 204 route (kills per-load console 404)
  54. d691649 2026-07-08 chore: syntax-verified session changes, v0.1.1 → v0.2.0 (session close)
  55. ee864df 2026-07-08 Schedule unsubscribe scan (launchd com.steve.dw-pitch-unsub-scan, 8am+8pm) — auto-honors client opt-outs with ?apply=1, logs every run; plist versioned in repo
  56. e2ce4dc 2026-07-08 auto-save: 2026-07-08T06:34:26 (1 files) — scripts/scan-unsubscribes.sh
  57. a9f7c6a 2026-07-08 CAN-SPAM: compliant footer (physical address 15442 Ventura Blvd #102 + UNSUBSCRIBE) on every send; suppression list honored at send (not overridable); tightened unsubscribe scanner (to:info@ + opt-out-at-start, dry-run by default, ?apply=1 to suppress)
  58. cc4f468 2026-07-08 Stop leaking internal 'From job: dw-pitch-followup' banner onto client emails (no_source_tag:true); verified sent body is clean
  59. ff19558 2026-07-07 yolo/contrarian fixes: build-time TODAY (fix aging bug) + 30-day double-email frequency guard at send (list1∩list2 dedup) with 'Send anyway' override
  60. d191c5c 2026-07-07 Auto-swap to a thank-you letter when client has a BOOKED order since sampling (references the order + project); quote-since-sampling still gets the follow-up (chase the close)
  61. 4f8a57a 2026-07-07 Flag invoices placed SINCE samples sent (possible conversion): card banner + panel detail with #, total, sku/item, quote/booked, date
  62. b6e5737 2026-07-07 Fix sticking Send button (reset #pSend/#pRegen/#pCopy on panel open); stamp emailed date/time in panel+card+sendstat; keep permanent sent-log.jsonl of every email + /api/sent + 'Sent log' viewer
  63. a4a77d7 2026-07-07 Make panel 'Send now (info@)' prominent — filled gold, bold, right-aligned with divider (was subtle outline, easy to miss)
  64. b2b886f 2026-07-07 Email: thumbnail + product-link gallery for recent samples (dw_unified sku→handle/image, dashed-sku match, ACTIVE-only links); panel shows thumbnails too; separate sample-reminder heading from list
  65. eb905c7 2026-07-07 Letter greeting uses FileMaker contact first name (Find-a-client Name field); block letter + red 'Reorder Samples??' when samples ordered but 0 shipped (panel Generate disabled too)
  66. 2246a8e 2026-07-07 Rewrite client letter to spec: ~3 sentences, client-type aware (designer/architect trade line), final-purchase ask, witty stock/samples ask, project-details line, ends w/ question, rotating Steve/Samantha/Marcus sign-off, sample list w/ dates, url+phone (HTML href on send), PS; no new-year/no mfr#; fix name parsing (parentheticals/ALL-CAPS)
  67. a350bea 2026-07-07 Right-panel detail view (context+last-corresponded on click+letter); quote/booked per invoice; lifetime sales (booked-only) on card+panel; current project from invoice sidemark; lifetime-sales sort
  68. 5305246 2026-07-07 Expand sort to all fields incl Invoice total (merch_total); add sort control to One-list view (defaults to invoice-total desc)
  69. e3aa21c 2026-07-07 Revert invoice links to file-open (skip GotoInvoice deep-link for now)
  70. 43c0d5a 2026-07-07 Invoice links: enable fmp:// record-jump (USE_FM_SCRIPT=true → GotoInvoice script param)
  71. 56b2381 2026-07-07 Enrich cards with samples sent/pending + merchandise invoices (>$250, real orders) w/ fmp links + total; MERCH_MIN=250; sample SKUs shown as-is in admin details
  72. 28a382b 2026-07-07 auto-save: 2026-07-07T14:31:09 (2 files) — public/index.html scripts/build-lists.js
  73. c660a28 2026-07-07 Compact cards + Columns/One-list layout toggle + ▸details expander (samples/merch/last-corresponded); lazy /api/lastcorr via George
  74. 306b791 2026-07-07 Add 'Send now (info@)' — emails generated letter via George info@ account with external-send approval token (Steve-authorized), confirm-guard + in-thread + persisted sent marker
  75. 182e2a6 2026-07-07 auto-save: 2026-07-07T14:01:00 (2 files) — public/index.html server.js
  76. 5d7759e 2026-07-07 Redesign viewer: 3-column board (all lists at once) + List/Grid toggle + density scale; per-column sort, cross-column select/export
  77. 8a5b1ac 2026-07-07 Frontend: build API URLs from location.host so fetches work even when page opened with inline credentials
  78. 0524e78 2026-07-07 Skip Basic Auth for direct-loopback access so the localhost viewer loads without inline creds (tunnel still gated)
  79. 2507156 2026-07-07 chore: version bump (session close — anti-hallucination guardrails)
  80. 9abe8a2 2026-07-07 pitch-followup: anti-hallucination guardrails + LLM reliability
  81. 9027026 2026-07-03 chore: macstudio3 migration — reconcile from mac2 + repoint paths (stevestudio2→macstudio3, node/npm/npx→/opt/homebrew)
  82. d2a48d9 2026-06-30 ui: show last-sample-sent date as a chip on every card (uses existing when_iso; removed redundant .when line)
  83. 351e8f9 2026-06-30 Pitch follow-up: hide mfr# from UI + client letters (toggle), LLM-customized letters, Generate/Regenerate buttons
  84. 91a8b82 2026-06-30 auto-save: 2026-06-30T14:41:08 (1 files) — deploy/
  85. a518ea6 2026-06-30 DW client/vendor follow-up pitch viewer: 3 read-only FileMaker lists + George-grounded letters + select/export (no sends)

Authors

Agents used

  • secrets-manager1

Skills used

  • /index6
  • /suppress4
  • /send3
  • /claude2
  • /code2
  • /followup-cache2
  • /sent2
  • /build-lists2
  • /booked2
  • /export2
  • /dict1
  • /path1
  • /query1
  • /writes1
  • /fm-notes1
  • /followup-batch1
  • /followup-analysis1
  • /deadlines1
  • /promises1
  • /status1
  • /day1
  • /emails1
  • /from1
  • /out1
  • /url1
  • /order1
  • /sent-index1
  • /shrink1
  • /enrich-disco1
  • /favicon1

Creative ideas + design notes

Commits with substantial prose (≥120 chars) — the rationale behind each move.

3828ac0 · 2026-09-25 · refresh.sh: retry build-lists up to 3x on transient Claris ID/Cognito 'Network error' FATAL (TK-12258)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7LB6rCwpA7ubJTqYzqXEX
b5f1281 · 2026-09-15 · security: add rel=noopener noreferrer to target=_blank links (yoloforever cycle 3)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UxvvaJ7p6VRZ4RzKDaBXqK
e26fbb5 · 2026-08-06 · Pitch drawer: render all Gmail correspondence as a table
The 'All emails with this client' drawer section now renders every message
(both directions, deduped across info@ + steve-office, up to the API max of
50) as a fixed-layout table — Dir / Date / Subject / Preview — with sticky
header. Each email is a <tbody class=em> (summary <tr> + hidden body <tr>),
preserving the .em/.emrow/.embody/.emcaret structure so the existing
click-a-row-to-read-full-body handler works with zero JS-handler changes.
Relabeled the section header to 'All Gmail correspondence'.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
705c715 · 2026-08-06 · Add repo-local pre-commit: lint staged launchd/*.plist
Blocks any commit that stages a malformed plist (mismatched tags, bad
schedule) via plutil -lint on the staged blob. Repo-scoped core.hooksPath
=.githooks so it runs even though this machine's global core.hooksPath
points at a non-existent dir. Prevents a repeat of the silent broken-plist
that froze the pitch board for a week.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
264deba · 2026-08-06 · Fix pitch-rebuild launchd: valid plist + once-daily 2:00 AM schedule
Root cause of stale board (data frozen at Jul 30 build): this plist was
malformed (opened <array>, closed </dict>) and was never installed in
~/Library/LaunchAgents, so the rebuild job never ran. Rewrote with valid
tags and a single StartCalendarInterval at 02:00 per Steve's requirement
(was 6:30/11:30/16:30). Installed + bootstrapped; RunAtLoad refreshed the
board to today.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fc4911d · 2026-08-06 · Add catch-all: unknown non-api GETs redirect to / instead of raw Cannot GET 404
Stray deep-links / browser-autofilled paths now open the viewer instead of
Express's raw 'Cannot GET /path'. Scoped so /api/* still returns JSON 404s
(never redirect an API call — fetch() must see the real failure).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
229cd17 · 2026-07-15 · fix(notes): FileMaker note-save silently no-op'd — write rep-1 bare key + read-back verify
Root cause: repeating-field rep 1 must be written as the BARE field name ("Internal notes"), not "Internal notes(1)" — the Data API accepts the (1) form with success code 0 but silently ignores it, so notes logged as saved but never persisted (verified: a real save was empty on read-back). Also updateRecord reports committed:true after any non-erroring PATCH without confirming the field changed. Fix: write bare key AND read the record back, throwing if the note is not actually present — never report a save we cannot see.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
5e218be · 2026-07-15 · pitch: Follow up? YES/NO chip on every card + per-column ⚡ Triage (batch, cached)
Server keeps a persistent follow-up cache (data/followup-cache.json): analyzeFollowup writes each verdict; drawer opens + a new POST /api/followup-batch (concurrency 3, skips <24h-fresh) fill it. GET /api/followup-cache feeds card badges at boot. Cards show a green "Follow up" / tan "Hold" chip from cache; ⚡ Triage per column batches all un-cached clients with live progress; opening a drawer lights that card immediately. All local Ollama, $0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
8e921dc · 2026-07-15 · pitch: auto follow-up triage — reads the email thread → Follow up? YES/NO + notes (delays, deadlines, status)
New /api/followup-analysis reads the client thread via George and runs local Ollama (hermes3:8b, $0) to decide follow-up yes/no with a reason, concrete notes (delays/deadlines/promises/status), and a deadline date. Drawer shows a prominent Follow up? badge (green YES / red NO) auto-loaded on open, cached 6h per client, with a ↻ re-analyze. Deadline sanitized to real date-or-empty.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
e039b5a · 2026-07-15 · pitch: click any email in the history to expand its full body
New /api/email?id=&account= fetches the full message via George and strips HTML to readable text. Each email row is now clickable → lazy-loads + expands the body inline (caret ▸/▾), collapses on re-click, cached per message.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
a4bc2e8 · 2026-07-15 · pitch: Details drawer shows full email history with each client
New /api/emails?email= (George read-only) returns all emails to/from a client across info@ + steve-office, deduped, newest first, with in/out direction from the From header. Drawer renders the thread list (direction chip · date · subject · snippet), lazy-loaded on open alongside last-corresponded.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
9aa4cdc · 2026-07-14 · pitch: letter panel shows product thumbnails + DW product-page links
renderLetterGallery draws a small strip under the letter — 40px thumbnail + link to the DW product page for each referenced sampled item (image/url from dw_unified). Shown on panel open. 476/600 list1 clients have images.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
c6994a4 · 2026-07-14 · pitch: list2 letter follows up on the specific QUOTE (number, total, items) not generic samples
New quote-followup branch in composeDeterministic for list2: cites the actual quote #(s), total, and quoted items with amounts, and asks to convert to an order. Sanitizes leaked dimension strings out of the project ref and strips empty "(Ref.)" from item names. Verified against a real $6,693.60 two-quote client.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
f9b6323 · 2026-07-14 · pitch: Sent log is now LIVE — merge Gmail Sent (recipient-enriched) with the tool log
georgeSentLetters now fetches each sent letter full message for its `to` (Gmail search omits recipient), bounded to 60 newest, parallel. collectSent merges live+local, dedups by recipient+day, 60s cache. Sent log + per-card emailed chip now show through today (was frozen at the last tool-send). Verified newest = Jul 14.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6c560f3 · 2026-07-14 · pitch: FIX critical George 401 — resolve GEORGE_AUTH from secrets master (restores sends + threading + last-corr)
The app resolved an empty George password, so every George call 401d — sends, reply-threading, and "last corresponded" were silently failing (and pm2 --update-env wiped the process-env cred on restart). Now resolves the canonical GEORGE_AUTH ("user:pass") from secrets-manager/.env, surviving restarts. Verified: lastcorr returns a real thread.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
c6d5609 · 2026-07-14 · pitch: card/UX batch — dismiss-completed, park vendor memos, quote/order label fix, FM deep-links, live sent-index, expandable columns
- Dismiss any card as ✓ Done: instant DOM removal + persisted, never re-shown (localStorage done: flag; filterSort/flatRows exclude)
- Park Vendor Memos Overdue (list3): dropped from board + bucket via PARKED set (un-park = 1 line); grid tracks now match visible column count
- Fix quote-vs-order contradiction: postFlag shows BOOKED orders only; drawer relabels "Quoted since we sent samples" when none booked
- Per-invoice details: drawer splits Orders vs Quotes, each row shows item detail; goodLbl drops stripMfr punctuation-junk items
- FileMaker deep-links: invoice# and client acct now Find the exact record (fmpInvoice/fmpClient script+param, USE_FM_SCRIPT on) — needs GotoInvoice/GotoClient scripts in FM
- Real "emailed on <date>" chip from server /api/sent-index (cross-browser, 311 recipients from the send log)
- /api/sent now merges the local log with a live Gmail Sent view (George), 60s cache, invalidated on send
- Expand/shrink any board column (⤢ toggle, persisted)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
a59c63b · 2026-07-14 · pitch: redefine "Invoiced · No Order" list as real quotes never booked (totals + details)
- buildList2 candidate pool flipped from sample-only (maxTotal<=$50) to real-dollar invoices
- main() keeps only accounts with an open merch quote (quoted_total>0) and NO booked order (lifetime_sales==0), deriving quote_total / quote_count / quote_items
- cards show "$X quoted · no order" chip + quoted item details; sorts now quote-based
- drawer reads "No orders booked · $X in open quotes" for these never-booked prospects
- list2: 57 accounts (e.g. $92,250 Briseyda Garcia quote, never ordered)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
9abe8a2 · 2026-07-07 · pitch-followup: anti-hallucination guardrails + LLM reliability
- Whitelist product names: the writer may ONLY name a pattern that's in the
  client's actual sampled set (buildFacts now returns allowed[]); empty →
  model names nothing, speaks generically. Reject-guard throws on any ™/®
  or 'X Collection' name not on the whitelist → falls back to the accurate
  deterministic draft. No invented collection names can reach a client draft.
- Fix subject-greeting leak (subject is now a standalone line) + guarantee
  the body opens with 'Hi <name>,'; strip stray ™/®.
- Reliability: keep_alive 30m + widen Ollama timeout 30s→90s so drafts stop
  cold-timing-out to the generic fallback. Verified across seeds.

File tree

19 files tracked. Click any to browse the source at HEAD.

Other build journals

← Dw Photo Capture  ·  all 4 projects  ·  Dw Product Class →

Export

commits.csv · feed.atom · project.json · commits.json

rendered in 1ms