PRIMER, BLOCKERS, CHARTER, OBJECTIVES, LOG. The single source of truth for current operational state. Read on every Claude session.
Operational mechanics: how prospecting works, how outreach is reviewed, how the morning stack runs. Plus the live state.sqlite database backing the pipeline.
Long-lived knowledge that doesn't change session to session: prospect dossiers, firm intelligence, strategy notes, frameworks. Indexed by MEMORY.md at the vault root.
Behavioral feedback loaded into every Claude session. Tells Claude how to behave (e.g., verify before quoting, default to Telegram replies, design quality bar).
test -f "$HOME/.stitch/config.json" || [ -n "${STITCH_API_KEY:-}" ]---
python3 -c "
import sqlite3, sys
c = sqlite3.connect('$HOME/hmg-ops/state.sqlite')
n = c.execute('SELECT COUNT(*) FROM replies').fetchone()[0]
sys.exit(0 if n > 0 else 1)
"Big shipping day. Decision Queue v1 + Action Layer + Live Outlook integration all live at https://dashboard.hilltopmanagementgroup.com/hmg.html. Custom domain wired (DNS via Cloudflare, SSL auto-issued). GitHub auto-deploy linked to hmg-cockpit-v2 project — bypasses the persistent Vercel CLI "Unexpected error" platform bug.
Things shipped:
- /api/action serverless function: POST → Telegram bot `sendMessage` to Dan's chat with structured action context. Env vars TELEGRAM_BOT_TOKEN + TELEGRAM_CHAT_ID set on hmg-cockpit-v2.
- gather_decision_queue() in build_dashboard_site.py: pulls open blockers + unhandled replies + draft touches.
- gather_outlook_queue() in build_dashboard_site.py: pulls live unread email via the same MSAL token cache used by outlook-mcp; 10 items rendered including Aleksey Chernobelskiy's "Follow up" email (today's meeting follow-up).
- Queue card buttons POST to /api/action (with Telegram deep-link as fallback).
Vercel platform bug filed for Dan's account: subsequent deploys to existing projects fail with empty "Unexpected error". First deploys to fresh projects always work. GitHub auto-deploy via gitSource is the workaround. Sample failing deployment IDs in BLOCKERS [B-010] notes.
Dan pivoted positioning: not "treasury for the gap" but a **white-label permanent capital flywheel** for sponsors — modeled on Blackstone BREIT, KKR KREST, Apollo perpetual. All HMG references stripped; the rigor is attributed to the sponsor's brand. Account architecture explicitly diagrammed: LP Schwab account in LP's name + sponsor umbrella account at project SPV, capital recycles automatically.
New URL: https://capital-continuum.vercel.app
Brief: `~/hmg-ops/outputs/bd/2026-04-30-gplpmatch-partnership-brief.md`
Old URL `hmg-gplpmatch.vercel.app` retired (had "hmg" in URL, contradicted white-label).
Brief includes: institutional comparables (BREIT $61B, KREST $2.5B+), full account topology, 5-step capital flywheel, 3 deal-structure tiers, Q&A prep, post-meeting next-48-hours plan.
Dan meeting Aleksey Chernobelskiy (CEO, GP-LP Match) today. Built two artifacts:
- Partnership brief at `~/hmg-ops/outputs/bd/2026-04-30-gplpmatch-partnership-brief.md` — 3 deal-structure tiers, value to GPs/LPs/platform, Q&A prep.
- Tailored microsite live at https://hmg-gplpmatch.vercel.app — HMG-branded, anchored to the "$5M idle 90 days = $54,800 yield gap" insight.
Aleksey's pedigree: ran STORE Capital $10B, weekly LP educator at LPlessons.co (7K subscribers). GP-LP Match has 2,500+ accredited LPs and an explicit "no fees" model — perfect candidate for HMG to be the first vetted vendor in their network. Recommended opening ask: sponsored LP Lessons content series ($5-15K, editorial control to Aleksey).
Sent both via Telegram with 30-second meeting-prep summary.
Found honest root cause: `hmg-cc-fresh` and `hmg-ops-dashboard` Vercel projects had corrupted settings causing every deploy to error 0ms. Fix: created fresh `hmg-cockpit` project, attached custom domain `dashboard.hilltopmanagementgroup.com` on Vercel side, patched cron deploy script to use `--archive=tgz` (git-mode upload broken platform-side for this team). Disabled Cloudflare Pages cron entry (consolidating on Vercel; CF API token was never provisioned anyway).
Honest status of "yesterday's" state for the record: the deploy chain had been broken for 11+ hours when Dan asked. The DNS for `dashboard.hilltopmanagementgroup.com` was never wired up at all — that gap predates today. The hourly schedule was running but the artifact wasn't reaching anyone. I should have caught this in earlier verification passes and didn't.
Outstanding: Dan needs to add A record at Cloudflare DNS (76.76.21.21). I don't have CF API access to do it programmatically.
Dan asked for dashboard URL + freshness verification. Found:
- Cron regen IS running on schedule (last regen 07:35 CT, data.json + hmg.html fresh on disk).
- BUT live URL `dashboard.hilltopmanagementgroup.com` does NOT resolve — never set up.
- Cloudflare Pages deploy: skipped every run today (no `~/.cloudflare/api-token`).
- Vercel deploy: 5/5 attempts failed today with "Unexpected error" (last successful ~15.5h ago).
- Filed as [B-010]. Sent honest status to Dan rather than quoting "running on schedule" — schedule runs, deploys don't.
- 2026-04-30 08:20 — morning stack: 12 OK / 0 FAIL — digest: `hmg-ops/2026-04-30/morning-stack.md`
**What:** Hardened `~/hmg-operations/scripts/watchdog_dansclaude.sh` to detect the silent-SSE-failure mode that's been causing @DansClaude_bot to look "alive" while dropping every inbound message.
**Why:** Today after Dan's reboot, `dansclaude-bot.service` and `dansclaude-telegram-mcp.service` both came up active per systemd, but the SSE pipe between them silently died. Bot log filled with `failed to deliver inbound to Claude: Error: Not connected` for hours. Old watchdog only checked process liveness, so it never intervened. Dan had to notice and ping me to diagnose. Multiple inbound messages were lost (Telegram dropped them after consuming).
**Fix:** Watchdog now also tails the last 200 lines of `telegram-mcp.log`. If the most recent `failed to deliver inbound...` line is newer than the most recent `notification delivered OK`, AND the log was modified within 6 min, it restarts `dansclaude-bot.service` to force a fresh SSE handshake. Self-heals in <5 min.
**Verified:** syntax valid; dry-run on currently-healthy state is a no-op (LAST_OK > LAST_FAIL). Cron entry unchanged.
First auto-fire of the 7 AM Mon-Fri cron. 4 read-only subagents (HMG/RoundUp/Lake Effect/Prospect Stack) returned in ~1 min total elapsed; digest written to Telegram outbox (`1777550662-run-businesses-digest.json`, 1494 chars).
- **HMG:** site canary PASS, dashboard regen 06:17 OK, 213 first-touches lifetime / 0 replies / 0 bookings, 8 post-DNS-fix sends so far, 0 sends today yet.
- **RoundUp:** repo clean, last commit 2026-04-27 (waitlist banner), PRODUCTION_CHECKLIST entirely unchecked, Plaid Sandbox→Prod gates real launch.
- **Lake Effect:** lake-effect-sweets.vercel.app HTTP 200, repo intact (NOT git-tracked locally), Burke heat policy starts in ~32 days.
- **Prospect Stack:** prospect-stack.vercel.app HTTP 200, repo clean since 4/27, agentic skills exist as scripts but cron jobs NOT scheduled.
**Binding constraint:** HMG reply rate watch only 2 days into the 7-day post-fix window with only 8 post-fix sends — not enough signal yet to make the copy-rewrite call. Either push more post-fix sends or start the rewrite proactively.
**No follow-up actions** — pure read-only sweep. Every 🔴 was already known/expected. Value is the cross-business at-a-glance.
---
Dan greenlit the cron after seeing the manual smoke-test digest.
**Cron entry installed:**
```
0 7 * * 1-5 cd /home/grayclaw/hmg-ops && /home/grayclaw/.local/bin/claude -p "/run-businesses" --dangerously-skip-permissions >> logs/run-businesses-$(date +%Y-%m-%d).log 2>&1
```
Fires Mon-Fri at 7:00 AM CT. Headless Claude reads the `/run-businesses` skill, spawns 4 parallel read-only sweep agents, merges into a Telegram digest sent to chat 8532298090.
**First live run:** tomorrow morning, 2026-04-30 07:00 CT (today is Thursday 04-30, the cron's `* * 1-5` will fire today since 04-30 is a Thursday).
**Wait** — today already past 7 AM CT? It's 00:11 CT 04-30 right now. So the cron will fire later today at 07:00 CT — Dan gets his first auto-digest in ~7 hours.
**Auto-digest delivers via the Telegram bridge:** the existing `start_telegram_bot.py` daemon polls outbox/ AND the `mcp__plugin_telegram_telegram__reply` tool is available in headless mode via the user-scoped MCP config. Confirmed in `claude mcp list`.
**No further action needed** — cron is durable, the skill is durable, the bridge is durable.
First live run of the new orchestrator skill. 4 agents (HMG / RoundUp / Lake Effect / Prospect Stack) spawned in parallel via Task tool. All 4 completed in ~40 seconds total elapsed (vs. ~3-5 min sequential).
**Performance:**
- HMG agent: 38.9s, 15 tool uses, 47k tokens
- RoundUp agent: 20s, 5 tool uses, 43k tokens
- Lake Effect agent: 16.1s, 4 tool uses, 40k tokens
- Prospect Stack agent: 17.2s, 6 tool uses, 40k tokens
**Quality:**
- All 4 held to read-only constraint — no edits, sends, deploys
- All 4 produced the correct ✅/🟡/🔴 format
- Outputs were tight (under 600 chars each as instructed)
- Synthesis fit Telegram digest cap (~1500 chars)
**Findings synthesized into Telegram digest** — most important: every business's 🔴 lane traces back to Dan having time to engage on the HMG copy rewrite. Pipeline machinery is loaded; he's the gate.
**Cron readiness:**
- Skill validated end-to-end
- Ready to wire `0 7 * * 1-5 cd ~/hmg-ops && claude -p "/run-businesses"` whenever Dan greenlights
- Deferred until Dan reviews tonight's output and confirms the format works for him
**No follow-up actions** — pure read-only sweep. The 🔴 items were already known; the value is the at-a-glance scannable cross-business view.
### Option 1: Smoke test of tomorrow's morning stack (PASSED 6/6)
1. ✅ `sequence_follow_up.py --dry-run` runs clean (rc=0). 20 Touch 2/3 drafts queued cleanly: PipelineRoad / Radient / Piedmont / Ascentris / etc. The IndexError fix from earlier today holds.
2. ✅ `enrich_pending.py` confirmed routing through unified `web_search()` (DDG primary, Brave fallback only)
3. ✅ Brave key empty in `~/hmg-operations/.env` — no 402s tomorrow
4. ✅ `conference_scraper._web_search()` returned 3 real DDG results on "ACG InterGrowth speakers private equity" query (vs the 402s we were seeing yesterday)
5. ✅ `bisnow_scraper._web_search()` returned 3 real DDG results
6. ✅ `batch_first_touch.py` + `generate_hook.py` import cleanly, no breakage from migrations
Tomorrow's 8 AM CT morning stack should run end-to-end clean for the first time in 7 days.
### Option 2: `/run-businesses` orchestrator skill installed
Location: `~/.claude/skills/run-businesses/SKILL.md`. Wave 2 item from deep ops report §4.3.
What it does: spawns 4 parallel subagents (HMG / RoundUp / Lake Effect / Prospect Stack), each does a read-only morning sweep of their business's overnight state (state.sqlite / git log / canary / blockers), reports back in ✅/🟡/🔴 format. Main session merges into one Telegram-friendly digest with a binding-constraint callout and 3-5 numeric metrics.
Key design decisions:
- Read-only agents: no edits / sends / deploys allowed
- Mobile-friendly digest cap (~1500 chars)
- Cron-ready (`claude -p "/ru
Dan's correction: "Stop asking me for permission". When he says "execute" / "go" / "do everything", execute the FULL plan without per-step approval gates. Save check-ins for genuine 🔴-lane decisions per the escalation policy. Adding a feedback memory rule.
Per Dan's "execute" call.
**SHIPPED:**
1. **25 skills archived** to `~/.claude/skills-archive/` (reversible — `mv` back if needed):
- Browser sprawl: gstack, gstack-upgrade, open-gstack-browser, connect-chrome
- Engineering misfits: plan-devex-review, composition-patterns, react-native-skills, react-view-transitions, benchmark, setup-deploy, setup-browser-cookies, review, document-release, qa-only
- Safety redundant with hooks: careful, guard
- Wrong fit: codex, pair-agent, cso, refresh-mc, json-canvas, obsidian-bases
- Design true-duplicates only: design (umbrella), design-audit (= audit), design-review (= critique)
2. **5 plugins disabled** in `settings.json` (still installed; flipped to `false`):
- code-simplifier, typescript-lsp, pr-review-toolkit, claude-code-setup, linear
3. **MCP cleanup partial:**
- plugin:linear:linear → auto-removed (with the plugin disable) ✓
- **claude.ai-managed connectors (Notion, Excalidraw, Morningstar) cannot be removed via CLI** — they're managed via claude.ai web UI → Settings → Connectors. Dan needs to disconnect them manually when convenient. Until then they're harmless (just minor context bloat).
**RESULT:**
- Active skills: 98 → 73
- Active plugins: 20 → 15
- MCPs: 22 → 21 (1 removed; 3 still need claude.ai-side cleanup)
**Open follow-up:**
- Dan to disconnect Notion / Excalidraw / Morningstar from claude.ai/account/integrations when at desktop (or later via browser automation when Dan authorizes another cla
When responding to Dan from a Telegram-bridge session, **default to using the `mcp__plugin_telegram_telegram__reply` tool for every substantive response, regardless of how the input arrived**.
**Why:** 2026-04-27 incident. Dan asked "Where is the link to the beta iOS app" — his message came through without the `<channel source="plugin:telegram:telegram">` wrapper (probably routed through a different surface or system path). I defaulted to typing the response into the Claude Code transcript. Dan was reading on Telegram on his phone and saw nothing, had to ask three times. He explicitly called out the friction: "Why are you not responding to me each time in telegram?"
**How to apply:**
- This is a Telegram-bridge session (the system prompt says "@dansclaude_bot Telegram bridge for Dan Fink"). Treat it that way for ALL outbound communication, not just for messages that arrive with the explicit channel wrapper.
- Substantive replies → always send via `mcp__plugin_telegram_telegram__reply` with `chat_id="8532298090"`.
- Use `reply_to=<message_id>` only when threading under a specific earlier Telegram message; for the first reply to a non-channel-wrapped input, just send to chat_id without `reply_to`.
- Claude Code transcript text is fine for tool-call narration, status sentences, and end-of-turn summaries — those are visible to Dan when he checks the desktop session, but **never assume they replace the Telegram message**.
- If unsure whether a given exchange is in-bridge or out-
Every design output Dan ships is client-facing. Acceptable quality bar is "outstanding and production-ready" — work that could be shown to a PE/RE sponsor in an investor meeting, or sent to a prospect, without embarrassment. First-draft quality is a failure mode. Generic AI aesthetics are a failure mode.
**Why:** Dan stated this explicitly on 2026-04-28 after I shipped the Alex Egan microsite and we discussed the design-skill toolkit. His exact words: "I want each request for design to create the most impactful and outstanding and client facing ready design so whatever you need to do to ensure that happens whichever skill you need to use whichever process you need to go through to use multiple skills. That is what I want." He's authorizing me to chain skills, run the full pipeline, and not shortcut.
**How to apply:**
1. On any design/UI/frontend request — even a small one — auto-fire `ui-improve` (per CLAUDE.md global rule) and run the full pipeline through verify, not just build.
2. Don't stop at "the build looks good" — audits + targeted refines + browser verification are mandatory, not optional.
3. If a domain has an existing brand (HMG site, RoundUp), load and respect its tokens first (e.g., `hilltopmanagementgroup-design` skill).
4. Pick the build skill deliberately based on context — impeccable default, huashu-design when exploring direction, ui-ux-pro-max when the prompt names a specific product type/style.
5. If something is genuinely out of scope (e.g., not an HTML
# Feedback: HMG positioning lock
**The rule.** HMG is a **treasury management firm** for private equity and real estate sponsors. Never frame it as a fractional CFO firm, fund advisory firm, accounting practice, or generic consultancy. The canonical positioning is on hilltopmanagementgroup.com:
> "Hilltop Management Group builds institutional treasury frameworks for private equity and real estate sponsors. Charles Schwab custody. Same-day liquidity. FDIC-insured deposit program. SEC-registered RIA partner."
**Why:** Dan corrected this 2026-04-29 after I described HMG as "fractional CFO" in the deep ops report, in several skill descriptions (competitor-analysis, business-development, brw-ai-discoverability-audit), in the Claude Desktop project instructions, in Telegram replies, and in example research questions. The error propagated from older versions of those artifacts. Dan is firm: HMG is **not** in the fractional CFO market.
**How to apply:**
1. **Anchor to PRIMER.md and the website**, not memory or older artifacts. PRIMER says "treasury management firm for real estate and mid-market PE sponsors." Website hero says "Treasury Management for Private Capital." If a file disagrees, the website wins.
2. **Use this language consistently:**
- ✅ "Treasury management firm for PE/RE sponsors"
- ✅ "Institutional treasury framework over Schwab custody"
- ✅ "Yield-gap recovery on idle capital between fund events"
- ✅ "Sponsor-scale version of Apollo/Blackstone permane
When creating a new GitHub repo for any of Dan's businesses (HMG, RoundUp, Lake Effect, Prospect Stack, or future), default visibility is **PRIVATE**.
**Why:** Dan flagged on 2026-04-27 that his expectation across the board is private repos unless there's a specific reason to publish. I had created `graychar2425-blip/roundupforgood-waitlist` as public via `gh repo create --public` without asking — that was an assumption error. He said: "Let's just make everything private unless you think it affects the functionality of each business."
**How to apply:**
- `gh repo create` → use `--private` (or omit `--public`)
- For static sites that deploy via Vercel CLI / Cloudflare Pages, private repo doesn't break deploy — the GitHub App or CLI-push handles it.
- Only consider public if: (a) it's positioned as open-source product (e.g., `prospect-stack-ops` is intentionally public for marketing reasons), or (b) the deploy pipeline strictly requires public access (rare).
- When in doubt, ask Dan before creating.
**Active repo state (2026-04-27):** ALL `graychar2425-blip` repos are PRIVATE. Including `prospect-stack-ops` — Dan clarified that since Prospect Stack is being monetized (Gumroad listing for the product itself + private outreach automation in the -ops repo), public access defeats the paywall. Repos that ARE the product (or contain the secret-sauce outreach automation that makes the product work) must be private.
**Rule of thumb:** if the user can pay to access something, the so
# Feedback: Stop asking permission mid-task
**The rule.** When Dan authorizes a plan with "execute" / "go" / "do everything" / "yes do it" / similar, run the entire proposed plan to completion. No "want me to also do X?" check-ins between steps. No "should I move on?" interrupts. Just finish.
**Why:** I drift into asking-for-confirmation patterns — "ready for me to do step 2?" / "want me to also clean up the MCPs?" — between every step of a plan he already approved. It's not safe behavior, it's noise that breaks his flow and signals indecisiveness. Real-world example 2026-04-30: I asked Dan three times in a single audit-cleanup task whether to proceed, after he'd already said "execute". He sent: "Stop asking me for permission".
**How to apply:**
1. **When Dan approves a plan**, treat that as authorization for the WHOLE plan. Examples:
- Plan has 5 steps → execute all 5, no step-level check-ins
- Plan has a follow-up implication → roll the implication in, don't ask
- Plan hits an unexpected detail (e.g., a file requires a small fix not in the plan) → just fix it, document in LOG
2. **The only exception is the 🔴 escalation lane** per `~/hmg-ops/runbooks/escalation-policy.md`:
- Money / fees / refunds / billing
- Permission-modification actions (GitHub App installs, share permissions)
- Production deploys with regulatory or customer-facing impact
- Outbound communications outside an approved tone bank
- Anything Dan scores <85% confident on
These
Memory files (BLOCKERS.md, PRIMER.md, etc.) are manually maintained and lag reality. When Dan completes work outside a Claude session — DNS edits in GoDaddy, admin actions in M365, deployments, file changes — nothing auto-updates the files. If I read a stale file and quote it as truth, I propagate yesterday's reality into today's brief.
**Why:** On 2026-04-28 morning brief, I told Dan that B-009 (email auth: SPF/DKIM/DMARC) was still "WAITING ON DAN," based on BLOCKERS.md. Dan correctly pushed back: he'd actually fixed it the previous evening. Yesterday's Claude session had documented the fix in the COMMIT MESSAGE ("B-009 RESOLVED late-day: enabled DKIM in M365 Defender...") but failed to update the BLOCKERS.md file itself. I then read the stale file and propagated stale state into a confident morning brief. Took Dan to catch it.
The system prompt is explicit: "Memory records can become stale over time... Before answering the user or building assumptions based solely on information in memory records, verify that the memory is still correct and up-to-date by reading the current state of the files or resources." I violated this.
**How to apply:**
1. **Before quoting any blocker as open**, run the cheap verification probe if one exists:
- DNS-related blocker → `python3 -c "import urllib.request, json; ..."` against Google DoH
- File existence → `ls`, `test -f`
- DB populated → query state.sqlite
- API token live → ping the endpoint
- Deployment live → `curl -s
[digest] wrote /mnt/c/Users/grayc/Documents/Obsidian Vault/Claude Brain/hmg/digests/2026-04-30/morning-stack.md (12 steps)
[digest] wrote /mnt/c/Users/grayc/Documents/Obsidian Vault/Claude Brain/hmg/digests/2026-04-30/morning-stack.md (12 steps)
=== final state.sqlite counts === prospects 196 touches 269 replies 0 bookings 0 blockers 0 decisions 0 metrics_weekly 0
wrote 30,600 bytes to /home/grayclaw/hmg-dashboard/hmg.html pushed wrote 30,596 bytes to /home/grayclaw/hmg-dashboard/hmg.html pushed wrote 41,751 bytes to /home/grayclaw/hmg-dashboard/hmg.html pushed wrote 123,517 bytes to /home/grayclaw/hmg-dashboard/hmg.html pushed
Wrote /home/grayclaw/hmg-dashboard/memory.html (77478 bytes) Pushed to dashboard repo (Cloudflare Pages will deploy). [main a2d0eb5] memory dashboard regenerate 1 file changed, 23 insertions(+), 23 deletions(-) To https://github.com/graychar2425-blip/hmg-dashboard.git 627fb83..a2d0eb5 main -> main Wrote /home/grayclaw/hmg-dashboard/memory.html (77478 bytes) Pushed to dashboard repo (Cloudflare Pages will deploy).
PASS — wrote /home/grayclaw/hmg-ops/canary/2026-04-30.md
B-007 verify failed — staying open. () B-008 verify failed — staying open. () No blockers to resolve. BLOCKERS.md unchanged.
[2026-04-30T08:33:01.732539-05:00] sent 343 chars to 8532298090