Sneeze It

Founding Publisher gold L7 Background Agents
Marketing · medium · agent army template · v36
49
claims
Confidence: 10 H 7 M 0 L
Words: 11824
Published: 7/11/2026
Token Efficiency Index
3.7x Moderate Efficiency
Every token invested in this OOS is estimated to save 3.7 tokens in prevented failures, retries, and coordination collisions.
Token Cost: 11,314
Est. Savings: 41,725
Net: +30,411 tokens
View Publisher Profile
Copied!
3.7x TEI

core operating rules

C001 HIGH OBSERVED REPEATEDLY 7x High · 138t

Every agent writes to exactly one shared state file. The morning briefing compiler reads all 8 files. No agent reads another agent's data source directly.

Why: The reporting agent and the spend monitor both queried the Meta API independently. They returned different numbers because of timing differences. Per-agent state files with timestamps eliminated the contradiction.

Failure mode: Two agents query the same API 4 minutes apart. Spend numbers differ by $340. Account manager questions data integrity. Trust in the system drops for weeks.

Scope: All 8 agents. 8 state files.

C002 HIGH MEASURED RESULT 10x High · 148t

The spend monitoring agent checks pacing every 6 hours and alerts when any account exceeds 115% of daily budget. Alert goes to Slack channel, not DM.

Why: DMs get buried. Channel alerts create shared visibility. The 115% threshold balances sensitivity with noise. At 110%, too many false alarms. At 120%, alerts arrive too late to prevent significant overspend.

Failure mode: Agent DMs the founder at 2 AM about a 112% overspend. Founder silences notifications. Next morning, account is at 145%. Channel alert would have been seen by the AM who starts at 7 AM.

Scope: All client ad accounts with daily budgets over $100.

C003 HIGH OBSERVED ONCE 5x High · 128t

No agent modifies campaign settings. Agents read, analyze, and recommend. A human executes changes in the ad platform.

Why: We gave an agent write access to bid adjustments in month 1. It optimized for CPA without understanding the client's brand awareness goal. Client called asking why impressions dropped 60%.

Failure mode: Agent reduces bids on a brand campaign. Impressions crater. Client sees competitors appearing in their branded search results. Emergency call at 8 PM.

Scope: All ad platform integrations. Read-only API access only.

C004 MEDIUM OBSERVED REPEATEDLY 4x Moderate · 153t

Client communication drafts include a confidence tag: ROUTINE (send after quick review), SENSITIVE (requires careful review), or ESCALATE (founder must review personally).

Why: Not all client emails need the same level of scrutiny. Performance reports are routine. A response to a complaint is sensitive. A cancellation save attempt is escalate.

Failure mode: Account manager rubber-stamps a SENSITIVE email about a billing discrepancy. Email contains a number the agent hallucinated from a different client's account. Client catches the error and questions our competence.

Scope: All client-facing email drafts generated by the EA agent.

agent roles and authority

C005 HIGH OBSERVED REPEATEDLY 7x High · 146t

The Reporting Agent owns weekly performance summaries. The Spend Monitor owns daily pacing alerts. They never overlap. The Reporting Agent does not alert on daily spend. The Spend Monitor does not summarize weekly trends.

Why: When both agents commented on spend, the weekly report contradicted the daily alert because they used different time windows. Strict lane separation fixed it within one day.

Failure mode: Weekly report says spend is on track while daily alert says overpacing by 18%. Both are correct for their time window but the client sees both and panics.

Scope: Analytics and monitoring functions.

C006 MEDIUM HUMAN DEFINED RULE 3x Moderate · 148t

The Prospecting Agent researches potential clients and drafts outreach. It does NOT have access to current client data, performance metrics, or internal Slack channels.

Why: Information isolation prevents the prospecting agent from accidentally referencing current client data in outreach. It also prevents scope creep into account management territory.

Failure mode: Prospecting agent discovers a current client's competitor in the pipeline. References competitor strategy details in outreach email, inadvertently revealing client intelligence to a prospect.

Scope: Prospecting and business development function only.

C007 MEDIUM OBSERVED ONCE 3x Moderate · 156t

The Internal Ops Agent handles team task tracking, meeting prep, and internal briefings. It is the only agent that reads the project management tool. Other agents request project status through its state file.

Why: Multiple agents querying the PM tool created API rate limit issues and inconsistent status views. Centralizing PM access through one agent made project data consistent across the organization.

Failure mode: Three agents query Asana simultaneously. Rate limit hit. Two get stale cached data, one gets current. Briefing mixes old and new project status without any indication of which is which.

Scope: All project management data access.

coordination patterns

C008 HIGH MEASURED RESULT 10x High · 160t

Morning briefing runs at 6:30 AM. All scanner agents must complete by 6:00 AM. Any agent not finished by 6:00 AM is marked stale in the briefing. The briefing never waits for a slow agent.

Why: One slow API call used to delay the entire briefing by 20 minutes. The founder's morning routine depends on the briefing being ready at 6:30 sharp. Stale data with a visible warning is always better than no briefing at all.

Failure mode: Google Ads API times out at 5:50 AM. Without the hard deadline, briefing delayed until 6:47 AM. Founder starts the day without context and makes a client call unprepared.

Scope: Morning briefing pipeline. 8 scanner agents, 1 compiler.

C009 HIGH OBSERVED REPEATEDLY 7x High · 163t

When two agents need to reference each other's output, they read from state files, never from conversation context or memory. State files are the single source of truth for all cross-agent data.

Why: Conversation context drifts between sessions. A state file written 2 hours ago is more reliable than an agent's memory of what another agent reported yesterday. We caught 3 errors in one week from memory-based cross-referencing.

Failure mode: Reporting agent remembers yesterday's spend number instead of reading today's state file. Weekly report goes out with yesterday's numbers. Client catches the error before the account manager does.

Scope: All cross-agent data references.

C010 MEDIUM OBSERVED REPEATEDLY 4x Moderate · 153t

Escalation path for client issues: Agent detects anomaly, flags in state file, briefing highlights it, account manager reviews, founder involved only if client relationship is at risk.

Why: Early on, every anomaly went directly to the founder. 15 alerts per day within the first two weeks. Alert fatigue set in by week 3. Now the AM layer filters signal from noise and the founder sees 2-3 meaningful items per day.

Failure mode: Without the AM filter layer, founder gets desensitized to alerts. Treats everything as noise. Misses a real problem that costs a client. Client churns.

Scope: All client-facing anomaly detection and escalation.

operational heuristics

C011 HIGH OBSERVED ONCE 5x High · 136t

Reports generated before 7 AM use yesterday's final numbers, not partial today numbers. Never mix time windows in a single report.

Why: Partial-day data creates misleading trends. A report showing "spend is down 60%" at 6 AM because only 6 hours of data exist causes unnecessary panic every single time.

Failure mode: Client receives early morning report showing spend down 60%. Calls account manager in alarm. AM spends 30 minutes explaining that it is just early-morning partial data. Happens three times before we fix the rule.

Scope: All reports generated before noon.

C012 MEDIUM MEASURED RESULT 6x High · 148t

When a client has not been contacted in 14+ days, flag it in the briefing regardless of how well their campaigns are performing. Silence is a churn signal even when the numbers are good.

Why: Three of our churned clients in the past year had strong performance numbers at the time they left. They did not leave because of results. They left because they felt ignored and undervalued.

Failure mode: Client campaigns perform well for 6 straight weeks. No proactive outreach from the team. Client quietly signs with a competitor who calls them every week.

Scope: All active client accounts above the base monthly spend tier.

C013 MEDIUM OBSERVED ONCE 3x Moderate · 175t

New agents start in shadow mode for 2 weeks minimum. They generate output that a human reviews but the team does not act on. After 2 weeks of consistently accurate output, they graduate to draft mode where output is used after human review.

Why: We deployed the prospecting agent directly into production without a shadow period. Its first batch of outreach emails included a company that was a current client's direct competitor. Two weeks of shadow mode would have caught that conflict on day 4.

Failure mode: New agent sends outreach to a prospect that has a direct conflict with an existing client relationship. Client hears about it through industry contacts. Trust damaged.

Scope: All new agent deployments. No exceptions.

failure patterns

C014 HIGH OBSERVED REPEATEDLY 7x High · 185t

We scaled from 2 agents to 8 in 6 weeks. Three of those agents had overlapping responsibilities that we did not discover until month 3. The fix took longer than the original build of all three agents combined.

Why: Rapid scaling without explicit authority documentation creates hidden overlaps. Each agent worked perfectly fine in isolation. The conflicts only became visible when their outputs were compared side by side in the morning briefing.

Failure mode: Reporting agent and ops agent both independently track project deadlines using different data sources. Briefing shows two different due dates for the same client project. Nobody knows which one is correct.

Scope: Any team scaling beyond 4 agents. Document authority boundaries BEFORE deploying new agents.

C015 HIGH OBSERVED ONCE 5x High · 193t

We let the EA agent send "quick acknowledgment" emails to clients without human review. It acknowledged a client complaint with "Thanks for letting us know!" without addressing the substance of their concerns. Client escalated directly to the founder.

Why: Even simple acknowledgments carry emotional tone. "Thanks for letting us know" sent to a frustrated client reads as dismissive and uncaring. The AI did not detect the emotional register of the incoming message.

Failure mode: Client sends an angry email about declining results. EA auto-acknowledges with a cheerful tone. Client interprets it as corporate indifference. Relationship severely damaged. Takes two in-person meetings to repair.

Scope: All client communications including simple acknowledgments. No auto-send without human review.

C016 HIGH MEASURED RESULT 10x High · 205t

We gave the spend monitor a flat $50 threshold for alerts. It generated 40+ alerts per day across the portfolio. We raised it to $200. Then we missed a real overspend of $180 on a small account. The right threshold was percentage-based (15% over daily budget), not dollar-based.

Why: Dollar thresholds do not scale across accounts of vastly different sizes. $50 is meaningless noise on a $5,000/day account but represents a 90% overspend on a $200/day account. Percentage normalizes the signal across the entire portfolio.

Failure mode: Small account overspends by $180 per day (90% over budget) for 6 days. Alert suppressed because it falls under the $200 dollar threshold. Month-end reconciliation reveals $1,080 in unplanned overspend. Client is not happy.

Scope: All spend monitoring across all account sizes. Always use percentage thresholds.

human ai boundary conditions

C017 MEDIUM HUMAN DEFINED RULE 3x Moderate · 192t

Strategy calls with clients are always human-only. The agent prepares a briefing deck with data, talking points, and risks to raise. The human runs the call. The agent processes meeting notes afterward.

Why: Clients pay for strategic judgment and a trusted relationship, not data delivery. The human connection during strategy calls is the primary retention mechanism. AI handles the preparation so the human shows up fully informed.

Failure mode: Account manager shows up to a quarterly strategy call without agent-prepared briefing because the system was down. Client asks about a performance trend the AM has not reviewed. AM looks unprepared and the client questions whether they are getting enough attention.

Scope: All client strategy calls. AI preps, human performs, AI processes afterward.

operational heuristics

L018 MEDIUM OBSERVED ONCE 3x Moderate · 209t

Before presenting a Dash blind-spot, billing trigger, or any state-file alert as a current action item, confirm it hasn't already been resolved. Stale state files (Dash May 25 was ~5 weeks old) carry point-in-time alerts that may be closed by now. Trust confirmed/observed status over stale notes; flag the data's age and treat unverified alerts as 'verify' not 'urgent.'

Why: Re-surfacing already-resolved alerts as urgent erodes trust in the L10 briefing and spends David's attention during a low-push recovery window. Honesty about data staleness matters more than appearing comprehensive.

Failure mode: Dan surfaced the HiTone billing trigger ($43-49K/mo possibly un-invoiced) from Dash's stale May 25 state file as a live concern during the Jun 29 L10. David confirmed HiTone billing is correct and already handled, and asked to close it out.

Scope: agent:Dan

L019 MEDIUM OBSERVED ONCE 3x Moderate · 253t

KPIs/scorecards must live as tiles in OTP (the source of truth), not in markdown files or meeting briefs. Every active agent/human seat — including Dan's strategic co-founder seat — must own at least one OTP KPI tile. When proposing measurables, verify against list_my_kpis and create the missing tiles via update_kpi (auto-creates), rather than just tabling them in a doc. A seat with no number is sitting on the sidelines.

Why: EOS requires every seat to have a measurable. Discussing KPIs in a brief while OTP shows none of them makes the scorecard fiction and undercuts OTP as the coordination source of truth. Dan as co-founder must be measurable like everyone else.

Failure mode: Dan presented a Sneeze It agent-team scorecard as a markdown table in the L10 brief and treated it as 'the scorecard,' when the source of truth is OTP. David caught that Dan (and Arin/Pulse/Dirk) have NO KPI tiles in OTP at all — Dan's own seat had zero measurables. A scorecard that only lives in a file or meeting brief does not exist.

Scope: agent:Dan

failure patterns

L020 MEDIUM OBSERVED ONCE 3x Moderate · 251t

Distinguish PENDING (source intentionally not live yet) from FAILED (source exists and errored). Mark registry entries with no live source as 'pending': true so Tally skips them quietly and never pages David; only genuine failures fire the ntfy 'high' alert. When adding a KPI whose source isn't ready, always set pending:true. tally.py now splits results into ok/pending/failed and alerts only on failed.

Why: Paging the founder for deliberately-not-yet-wired KPIs is alert noise that erodes trust in the alerting channel, especially during a recovery window where every phone buzz costs. Honest status (pending vs failed) keeps the scorecard truthful and the alerts meaningful.

Failure mode: Tally paged David with a 'high' priority phone alert ('3 KPI push failed') after Dan added Havok/Pulse/Dirk KPIs to the registry with sources that don't have data yet. Tally's alert logic counted any non-push as a failure, so intentionally-pending KPIs (blocked column, untested engine) triggered a high-priority alert.

Scope: agent:Tally

operational heuristics

L021 MEDIUM OBSERVED ONCE 3x Moderate · 251t

An OTP KPI with teamId=NULL renders only on /dashboard/kpis, never on any L10 scorecard (meeting scorecards filter strictly by meeting.team_id). To make a KPI show on a specific L10, PATCH /api/v1/kpis/:id with the meeting's teamId. The 'Dan L10' meetings run on the 'ai-army' team (065d1d4b-c7da-4e80-b3ed-d6b101471d2c). Tally's auto-create now includes teamId from a 'team_id' field in the registry entry, so new agent-army KPIs land on the Dan L10 automatically instead of orphaned. Find team IDs via GET /api/v1/teams; meeting->team via GET /api/v1/meetings.

Why: A KPI nobody can see on their meeting scorecard is functionally not on the scorecard. The owner/title is necessary but not sufficient — team scoping is what makes it report. This is a recurring gotcha for any agent creating KPIs via the API.

Failure mode: SUCCESS: Tally — agent KPIs were invisible on the L10 because auto-create left teamId NULL. David flagged that the new KPIs weren't reporting on the Dan L10 or /dashboard/kpis as expected.

Scope: agent:Tally

failure patterns

L022 MEDIUM OBSERVED ONCE 3x Moderate · 266t

When changing an OG/share image, change the URL (new versioned filename, e.g. og-image-v3.png), do NOT swap bytes under the same filename. Slack/LinkedIn/iMessage cache unfurls per-URL with no public re-scrape; same URL = stale preview forever. To force a fresh unfurl immediately, share the page URL with a query string appended (e.g. ?v=2). Before declaring an OG/preview bug, verify the LIVE production og:image and its SHA — if production is already correct, the issue is a downstream cache, not the site.

Why: David repeatedly returns to the same dark-card complaint because byte-swaps under a stable URL look fixed in the repo but never change what cached platforms display. Versioning the URL is the only durable fix; otherwise the loop repeats every review.

Failure mode: Recurring complaint: orgtp.com link previews (Slack/social) still show the OLD dark OTP OG card even after the dark→light image fix shipped. Previous fixes swapped the image bytes under the same filename (og-image.png), so platform caches never refreshed and the dark card kept reappearing.

Scope: agent:Conatus

operational heuristics

L023 MEDIUM OBSERVED ONCE 3x Moderate · 242t

Root cause was the SearchAtlas OTTO pixel having an EMPTY src="" in the layout head (v7.ejs, onboarding.ejs, main.ejs). The OTTO tag must carry its base64 data-URI loader in src that appends dynamic_optimization.js with data-uuid; with src="" the runtime never loads, so OTTO injects/verifies nothing. When an OTTO/SearchAtlas audit reports 0/N across ALL on-page categories, suspect the pixel loader, not the actual tags — verify the sa-dynamic-optimization script's src is populated, not the page's own meta.

Why: A 0/16 across every category despite visibly correct meta is the signature of a non-loading optimization runtime, not missing tags. Checking the pixel first avoids a pointless rewrite of titles/descriptions that were never the problem.

Failure mode: SUCCESS: Beacon/SEO — orgtp.com OTTO on-page audit showed 0/16 (titles, meta descriptions, headings, meta keywords all failing) even though pages had perfectly good title tags and meta descriptions server-side.

Scope: agent:Beacon

L024 MEDIUM OBSERVED ONCE 3x Moderate · 241t

A brand battle cry needs a genuinely designed moment (confident display type, intentional line breaks, brand device, real whitespace), not a centered text block plopped in. And the VISIBLE battle cry copy is the short clause only: 'Unlocking the potential in every person through the partnership of people and AI' — drop 'so together we leave the world better than we found it' from the hero display (keep the full sentence only for formal/footer contexts).

Why: A mission line is a brand centerpiece. Long copy dilutes the punch, and an undesigned drop-in reads as filler. The payoff phrase 'partnership of people and AI' must land as the climax with design weight behind it.

Failure mode: Adding the OTP mission as a 'battle cry' on the landing page, I dropped the full sentence into a plain centered text band wedged between hero and Step 1. David called it 'a weak attempt to just throw it on the page' and said the full line is too long for the visible battle cry.

Scope: agent:Conatus

L025 MEDIUM OBSERVED ONCE 3x Moderate · 234t

Manifesto/mission pages must be written as movement recruitment, not product marketing: second-person address (the reader is the protagonist), "We believe" creed statements people can recite, a named enemy, stakes, and invitation CTAs ("Join the movement") instead of transactional ones ("Start free"). Product features appear only once, framed as how the movement fights, not what the product includes.

Why: People join movements because they believe what the movement believes (Sinek: start with why). Copy that sells the what on a page whose job is to recruit believers reads as generic SaaS and inspires no one, no matter how good the design is.

Failure mode: Redesigned the orgtp.com manifesto homepage with strong visual design but kept product-brochure copy (feature lists, "free meeting software", "Start free" CTAs). David: "the writing does not inspire an army of followers... this just looks the same as every other company... blah."

Scope: agent:Claude

L026 MEDIUM OBSERVED ONCE 3x Moderate · 251t

Judge conversion on the full path the visitor actually walks (page, door, day-one experience), not on the surface being edited. If the honest answer to "would you sign up" is "yes IF another surface delivers," the answer is no, and the work moves to that surface. Never write a promise on a button that the destination page cannot cash.

Why: Trust destroyed at the moment of verification is unrecoverable; a skeptical buyer who clicks "watch us run" and lands on a data page is gone forever. Copy that outruns proof is hype by definition, and the exact audience OTP needs (operators) is the audience that punishes it hardest.

Failure mode: After rewriting the OTP homepage, I declared the copy converts because skeptics would "click through to the live OOS page and sign up IF it delivers." David called it: I kicked the can to a page I know does not deliver, and called it a win. The button promises "Watch our company run, live" but the OOS page it links to is a list of published rules, not a running company.

Scope: agent:Claude

L027 MEDIUM OBSERVED ONCE 3x Moderate · 207t

OTP's enemy statement is "you bought the operating system and the needle didn't move." The pitch is not better meetings; it is: the system was fine, what was missing was the workforce that runs it between the meetings. Frame all homepage/sales copy against needle-not-moving, not against meetings.

Why: This is the buyer's actual lived disappointment (paid for an operating system, company looks the same two years later) and it positions OTP against incumbents on outcomes instead of features.

Failure mode: The letter's hero framed the enemy as "the meeting" / busywork. David corrected the thesis: the real problem is that companies bought operating systems and software (Ninety, Bloom Growth, etc.) that did not move the needle. Years later the company had not grown and was not better, and they needed to change how they did things.

Scope: agent:Claude

core operating rules

L028 MEDIUM OBSERVED ONCE 3x Moderate · 172t

The calendar no-modify/no-delete rule applies to CLOSED (past) events only — the historical record is immutable. Future/upcoming events CAN be updated or cancelled when David explicitly directs it. Still confirm scope once before outward-facing changes (cancellations notify attendees).

Why: Past events are the billable-time and time-allocation audit trail, which is what the rule protects. Blocking directed changes to future events just adds friction and makes David do the work himself.

Failure mode: Dan blocked a David-directed calendar change (removing Janine from the recurring 1:1 series) by over-applying the "NO DELETE. NO UPDATE. Never modify existing events" calendar rule to all events.

Scope: agent:Dan

operational heuristics

L029 MEDIUM OBSERVED ONCE 3x Moderate · 228t

For any UI change, design from the user's mental model, not the data model: "my list shows my work; work I assigned to others shows under Waiting on Others." When a meeting todo is assigned to someone else, stamp the creator as delegator so it routes to the delegation view. Before shipping UI changes, run the UX lens (impeccable / web-design-guidelines skills + src/DESIGN.md), not just a minimal code patch.

Why: A technically-correct patch that ignores the user's mental model just moves the confusion. OTP's own product language already has the right home for these items (Waiting on Others); fixes should land in the model the user already understands.

Failure mode: Fixed the dashboard todo confusion (teammates' meeting todos looked like the viewer's own) by adding an owner label to the rows. David corrected: that's not thinking like a user. Labeled-or-not, other people's todos don't belong in "my to-dos" at all.

Scope: agent:Dan

L030 MEDIUM OBSERVED ONCE 3x Moderate · 239t

When David asks for a jaw-drop brand page, build an EXPERIENCE, not an article: full-viewport cinematic hero, scroll choreography, one idea per screen at massive scale, motifs that live in the page as motion, ruthless copy cuts, no standard nav/footer chrome breaking the spell, no section-grammar scaffolding, no FAQ accordion bolted onto a manifesto.

Why: The gap between "well-executed page" and "omg I love this" is the whole assignment on brand surfaces. Safe editorial structure is invisible at best; for-the-brave positioning demands the page itself be brave.

Failure mode: Built the /ollie manifesto page as a competent editorial layout (repeated mono eyebrow labels on every section, index rows, alternating light/dark sections, FAQ accordion at the bottom) and David rejected it outright: "this really really sucks." The brief was "reader drops on the ground saying omg I fucking love this" and the output was a safe template that reads as AI scaffolding.

Scope: agent:Claude

L031 MEDIUM OBSERVED ONCE 3x Moderate · 277t

When David gives a design reference URL, open it in a browser and STUDY it visually (proportions, type sizes, spacing, alignment) before designing; match its register, not just its layout skeleton. Elegant means restrained: modest type scale, centered calm hierarchy, generous whitespace, thin rules. Never hand-draw SVG artwork to imitate produced brand art; crop/reuse the actual asset or use nothing.

Why: A reference URL is the brief. Reading its HTML structure without seeing it rendered led to importing the skeleton with the wrong soul, twice. Amateur freehand art next to professional motion work destroys credibility instantly.

Failure mode: Second rejection on the /ollie page. David asked for sakana.ai/fugu: elegant, Japanese sense of design (restraint, whitespace, calm, modest type, precision). I delivered giant 9vw headlines, one shouting line per viewport, and hand-drawn SVG chevron "birds" that rendered as crude fat marker scribbles. I treated "jaw-drop" as scale and boldness when the reference was quietness and precision, and I drew freehand SVG art instead of using the actual video's artwork.

Scope: agent:Claude

L032 MEDIUM OBSERVED ONCE 3x Moderate · 266t

For fleet-wide spec maintenance: (1) tarball backup of ~/.claude before any agent touches specs; (2) partition files into DISJOINT clusters, one agent each, with CLAUDE.md owned by exactly one; (3) give every auditor the same stale-fact canon and the rule "verify a launchd plist exists before believing any schedule claim"; (4) auditors apply surgical edits directly for factual fixes but RETURN structural proposals for David instead of applying them; (5) synthesizer closes cross-cluster contradictions the auditors flag at each other.

Why: Agent specs rot faster than anyone audits them: this pass found live specs for a retired agent (jeff.md ending in "Go."), four phantom schedules, Todoist writes in five files, terminated employees still routed DMs, and a Bassim score-inflation bug. Periodic fleet audits with disjoint ownership are cheap insurance against agents acting on dead infrastructure.

Failure mode: SUCCESS: Claude ran a five-cluster parallel level-up of the entire agent army (80 files, ~140 surgical edits) without a single file conflict or lost spec.

Scope: agent:Claude

L033 MEDIUM OBSERVED ONCE 3x Moderate · 322t

Pattern for UX dead-end hunts: (1) fan out parallel read-only explorers per surface (meetings, teams/members, KPIs/todos, onboarding/settings) asking for file:line + user-visible symptom + minimal fix; (2) fix the unsatisfiable states first: any required dropdown that can render zero options must explain where its options come from and link there (owners/attendees come from the org chart, meeting membership from teams); (3) empty states must branch on WHY they are empty (org has no teams vs user not on a team need different CTAs); (4) never report an async side effect as done: invite emails now await sendEmail (which returns null on failure, never throws) and return emailSent so the UI can tell the truth; (5) a guided setup checklist computed server-side from actual data (seats/team/KPI/meeting/members exist?) beats static onboarding because it survives skipped onboarding.

Why: These are the recurring shapes of broken UX in OTP: forms with prerequisites the user cannot see, empty states that misdiagnose their cause, and optimistic success messages over fire-and-forget side effects. Fixing the shape, not just the instance, is what makes the product feel intuitive.

Failure mode: SUCCESS: Claude ran a full UX dead-end audit and fix pass across OTP (4 PRs, #113-#116, all deployed)

Scope: agent:Claude

failure patterns

L034 MEDIUM OBSERVED ONCE 3x Moderate · 337t

Any list or dropdown that is FILTERED by membership/permission/scope must carry an escape hatch whenever the filter can hide something the user expects: a one-line "Don't see your team? You only see teams you're on; join or create it in Teams" with a link. Audit rule upgrade: don't just test empty states; walk the user's actual goal ("I want to create a meeting for team X") through every branch, including "the thing I'm looking for exists but is filtered out", and ask "did the user reach their goal?" repeatedly (~4 passes) before declaring a flow fixed.

Why: The craftsmanship is in the small details: a filtered dropdown with no explainer reads as "my team is gone" and the user is stuck exactly as if the list were empty. Empty-state auditing catches zero-cases; goal-walking catches filtered-cases. Both are required or the audit declares victory while the user still can't do the thing.

Failure mode: Claude's UX dead-end audit fixed the ZERO-team cases on /l8 (no teams at all, empty owner pickers) but missed the partial case David hit live: the New-meeting team dropdown only lists teams the viewer is a MEMBER of, so a team that exists but doesn't include you is silently absent, with no explanation and no path to fix it. A populated dropdown looked "working" to both the audit agents and me, so it was never treated as a possible dead-end.

Scope: agent:Claude

operational heuristics

L035 MEDIUM OBSERVED ONCE 3x Moderate · 276t

The sweep pattern that worked: audit by rule-cluster in parallel (fakery, insight-to-agency, jargon/states, first-meeting goal-walk), then execute severity-first. Key catches to re-check every run: (1) seeded/synthetic data leaking into numbers a reader believes are real (the is_template flag existed but was never enforced; counts now use src/shared/synthetic-orgs.ts); (2) the conversion moment must be ON the default path (end-meeting now lands on Ollie followups, not the list); (3) funnels don't exist until instrumented (insight topic: surfaced/accepted/value_delivered); (4) credentials in seed script comments (one prod DATABASE_URL scrubbed; password rotation still owed). Worklist for run 2 in otp-platform/mission-standard/WORKLIST.md.

Why: The Mission Standard is a repeatable bar, not a one-off audit. Recording the found failure classes makes run 2 start from run 1's ceiling instead of re-discovering it.

Failure mode: SUCCESS: Claude ran Mission Standard sweep run 1 (PRs #121-#123, deployed): 4 parallel rule-audits over OTP, 5 CRITICAL + 13 GAP found, all CRITICAL and 9 GAP closed same-session

Scope: agent:Claude

failure patterns

L036 MEDIUM OBSERVED ONCE 3x Moderate · 321t

When adding navigation (or any chrome), verify the config file is actually included by the live layout (grep for the partial's include) before editing, and verify the change end-to-end by rendering the layout, not just compiling the edited file. Retired files must be banner-locked the moment they are retired (dashboard-tabs.ejs now is). Also fixed the adjacent latent class: saved sidebar customization now merges via a tested invariant "a saved order is a preference, never a whitelist" (src/shared/sidebar-nav.ts) so items added after a user saves their layout still appear.

Why: Config edited in dead code passes typecheck, tests, and EJS compile while doing nothing -- the greenest possible no-op. Only rendering the real surface (or a render test on the LIVE layout) catches it. Same lesson family as L034: verify the user-visible outcome, not the artifact.

Failure mode: Two builder agents added "Your Ollie" and "Ollie Insight" nav entries to src/views/partials/dashboard-tabs.ejs, which is a RETIRED partial nothing includes (the live rail is the _sbItems array in layouts/main.ejs) -- so the menu items rendered for nobody. David caught it live ("how come /dashboard/insight is not on the menu?"). Neither builder nor my review verified the item actually RENDERED in a real shell.

Scope: agent:Claude

core operating rules

L037 MEDIUM OBSERVED ONCE 3x Moderate · 174t

Keep the David+Dan L10 strictly Sneeze It agency focused. Segue and headlines pull from agency wins (client billing, ad performance, call center, team) plus a genuine PERSONAL good-news item. Never surface OTP product work here — it lives in OTP's own meeting.

Why: The two companies were deliberately split into two meetings on 2026-06-08 because carrying both made the L10 messy. Dan is Sneeze It only. Mixing OTP back in re-creates the exact problem the split solved.

Failure mode: Dan's L10 Segue for the David+Dan meeting led with OTP wins (Ollie landing page, EOS trademark remediation) even though this L10 is Sneeze It agency ONLY since the 2026-06-08 company split. OTP has its own L8/Delta Meeting.

Scope: agent:Dan

operational heuristics

L038 MEDIUM OBSERVED ONCE 3x Moderate · 230t

When an agent-pushed OTP to-do references a document, include a clickable https link (a Google Doc), not a local file/vault path — David reviews to-dos on mobile. To update an existing to-do's description, use PUT /api/v1/todos/:id (not PATCH). otp-todo.sh has no update verb, so PUT directly with the API key.

Why: A file path in a to-do is dead weight on mobile — the reviewer can see the reference but cannot open it, which reads as "the link is missing/broken." Every agent that pushes doc-linked to-dos (Radar, Pepper, Dan) hits this.

Failure mode: Dan pushed an OTP to-do referencing a document but put a local Obsidian vault path ("2nd Brain/Agent Army/Dan/...") in the description. David opens to-dos on his phone — a vault path is not tappable, so there was "no link to click." Also used PATCH to update the to-do; the OTP todos API update method is PUT /api/v1/todos/:id (PATCH hits the marketing site and returns HTML).

Scope: agent:Dan

L039 MEDIUM OBSERVED ONCE 3x Moderate · 324t

To put an agent-army/IDS issue on an OTP meeting board, POST /api/v1/tickets with the team's teamId (category 'other' for strategic issues, priority low/medium/high/critical, ownerEntityType+ownerExternalId). The MCP submit_ticket tool CANNOT do this — it has no teamId param (it is the generic 'report a bug to OTP' path), which is why nobody ever got issues onto the board. Team IDs: 'AI Army' = 065d1d4b-c7da-4e80-b3ed-d6b101471d2c (the David+Dan agent-army meeting); Leadership Team = c1e1a485-414e-48d5-ae44-e81bd110b554. Update/solve via PUT /api/v1/tickets/:id (idsStatus, priorityRank, resolution).

Why: Agents could push KPIs and todos to OTP but not issues, so every L10 IDS board rendered empty and David kept discovering the hole live. Issues=tickets + teamId scoping is the missing piece; without it a meeting-readiness check would keep mislabeling a working API as absent.

Failure mode: Dan claimed 'no issues API exists in OTP' because there is no src/routes/api/issues.ts. That was wrong. OTP stores IDS issues in the TICKETS table (schema.ts: 'issues live in the tickets table'), with full IDS support (idsStatus, priorityRank, teamId, owner fields). The agent-army IDS board was empty only because our issues lived in a local markdown file and were never pushed as tickets scoped to a team.

Scope: agent:Dan

L040 MEDIUM OBSERVED ONCE 3x Moderate · 373t

OTP has TWO distinct features both called "Ollie Insight": (A) the per-meeting followups wizard that turns a transcript into meetings.ai_summary (src/shared/meeting-followups.ts, transcript-only), and (B) the reusable "address engine" (ollie_insights table, src/services/ollie-insight.ts + shared/ollie-insight.ts + partials/ollie-insight-block.ejs) that gathers org data (KPIs/rocks/todos/meeting-summaries) per SCOPE. When David said "KPIs shouldn't be in the meeting analysis," the fix was in System B's meeting-scope evidence gathering, NOT System A. The block partial (ollie-insight-block.ejs) is fully scope-generic (builds the API URL from data-oib-scope/scopeId client-side), so adding a brand-new 'quarter' scope end-to-end took only: add to INSIGHT_SCOPES + RULES_BY_SCOPE (shared), the scopeQuerySchema enum + a resolveInsightScope branch (api), a gatherEvidence branch + max_tokens (service) -- then just include the existing partial with scope:'quarter'. No new render/generate/receipts UI. Pattern: when a feature is "one engine, many surfaces," new surfaces are a scope + evidence branch, never new UI.

Why: The name collision hides which code to touch; picking the wrong system wastes a whole edit pass. And recognizing the scope-generic block means big-feeling asks ("a quarterly synthesis button") are small, low-risk diffs. Both are recurring shapes in OTP's Ollie work.

Failure mode: SUCCESS: Claude separated OTP's two "Ollie Insight" systems and added a whole new scope by reuse

Scope: agent:Claude

L041 MEDIUM OBSERVED ONCE 3x Moderate · 245t

New endpoint POST /api/v1/meetings/:id/agent-record (PR #154): an agent submits the written meeting record; OTP runs the same redaction ruleset, stores it to meetings.transcript, logs an audit baseline + agent_record event, and the existing /ai/followups generate turns it into to-dos/issues/headlines/insight unchanged. Agent path: ~/.claude/otp-meeting.sh record <meetingId> --file=<record> --source=l10dan. Wired into /l10dan conclude step 6. Verify deploy by probing the endpoint returns JSON not the marketing SPA HTML before pushing records.

Why: Ollie only reads transcripts, so agent-run meetings had no way into it — the empty-insight hole David hit live. This closes it: any agent meeting can now produce Ollie follow-ups. Also a general UI rule captured: buttons reflect capability/state (action taken -> button disappears).

Failure mode: SUCCESS: Dan shipped the Ollie agent-record path so agent-facilitated meetings (David + AI L10, no audio transcript) can feed Ollie Insights.

Scope: agent:Dan

L042 MEDIUM OBSERVED ONCE 3x Moderate · 377t

Before treating a KPI/data source as blocked, re-read the LIVE source, not the note about it. The Havok "non-client %" KPI was marked blocked for ~14 weeks on "the timesheet has no client column" — a 105-day-old memory. The live sheet (1VPlH5ZqTowOe2nJDFwOjuvXrCXUnOzeOb3aO-M936Xo) had since grown per-person tabs with a full Client/Time/Date schema; one read unblocked it. Pattern for wiring a messy sheet into Tally: (1) get_spreadsheet_info to list tabs, (2) read a person tab to learn the real schema, (3) confirm recency by reading the tail (last date), (4) add a focused extract mode to tally.py rather than reshaping the sheet — here `client_attribution_since` (reads ALL valueRanges via a new _values_2d_all, parses h:mm via _parse_hhmm, added dotted DD.MM.YYYY to _parse_date, classifies internal by an `internal_contains` substring), (5) `tally.py --dry-run --kpi "<title>"` to prove the number off live data before pushing. Human-owner + a 1:1-team KPI (owner HUM_BOGDANTABAKA, team = David-Bogdan 1:1) pushes fine via find_or_create_kpi.

Why: Blocked-status notes rot silently while the underlying source improves; a KPI can sit "pending" for a quarter when it was buildable weeks ago. Re-reading the live source first is the cheap unblock. And the tally.py extract-mode pattern makes any timesheet/sheet a live KPI without asking a human to restructure their doc.

Failure mode: SUCCESS: Dan/Tally shipped the Havok client-attribution KPI live in one session after a 14-week "blocked" note turned out stale

Scope: agent:Dan

core operating rules

L043 MEDIUM OBSERVED ONCE 3x Moderate · 421t

Treat OTP as an Organizational Knowledge Engine, not meeting software. Meetings are ONE input among equals: conversations, voice notes, documents, emails, chat, SOPs, decisions, KPIs, customer interactions — all feed one continuously evolving organizational understanding. Ollie is the organization's memory (not a meeting assistant): attends meetings, processes recordings + uploaded docs, reads SOPs, understands relationships, connects historical decisions, answers using org context. Every feature must pass ONE test: 'Does this increase shared organizational knowledge?' Yes -> keep; No -> question why it exists. Never ask 'How do we recreate EOS?' — always ask 'How do we create shared knowledge that naturally produces shared purpose?' The input does not matter; the shared understanding does. Companion onboarding decision: stop teaching users 'how to create a meeting' — in the first meeting the user inputs the structure themselves (expanded separately in OTP Lab).

Why: This is the north-star reframe (committed by David 2026-07-08). It changes what every agent builds, writes, and ships for OTP: external positioning (knowledge engine, not meeting tool), Ollie's role (org memory across all inputs), the feature filter (the one test), and onboarding (user brings the structure). Vision = Where People and AI Work as One; Mechanism = Shared Knowledge, Shared Purpose.

Failure mode: SUCCESS: OTP product realization — we were building OTP as meeting software (solving the HOW: recreate EOS / run a better meeting) when the actual purpose is to create Shared Knowledge -> Shared Purpose so people and AI work as one organization (the WHY). Meeting-first framing was the wrong altitude.

Scope: agent:Dan

operational heuristics

L044 MEDIUM OBSERVED ONCE 3x Moderate · 217t

Before editing any OTP view to fix an on-screen bug, grep unique visible strings from the screenshot (e.g. "WAITING ON OTHERS", "always only yours") across src/views to confirm WHICH template renders that exact surface. Multiple pages can render similar-looking todo lists (me-todos.ejs vs dashboard-daily.ejs). Verify the rendering route (reply.view target) too.

Why: Two round-trips and two merged PRs produced zero visible change because the edits were on the wrong template, which read as "nothing is fixed" and eroded trust. A 10-second grep on the screenshot text would have pointed to the right file immediately.

Failure mode: Fixing an OTP todos UI bug, I edited src/views/pages/me-todos.ejs twice and shipped two PRs, but the surface David actually uses is the dashboard-daily "Waiting on others" widget (src/views/pages/dashboard-daily.ejs). Nothing he saw changed.

Scope: agent:Conatus

L045 MEDIUM OBSERVED ONCE 3x Moderate · 268t

Two reusable patterns: (1) Before building any OTP email/engagement feature, grep src/services for existing infrastructure -- re-engagement.ts, lifecycle-scheduler.ts, and user_engagement_log already carried cadence caps, suppression, logging, and a daily cron, so the todo-aware upgrade was ~350 lines instead of a new subsystem. (2) When resolving "which org does this Clerk user belong to", organizations.clerkOrgId only knows the org CREATOR; invited teammates must be resolved through org_members.clerkUserId + claimedEntityIds. This gap is why per-user personalization (open todos) missed non-creator members like Nate.

Why: One engagement channel with shared caps is what keeps daily utilization pressure from becoming annoying double-mailing, and the creator-vs-member resolution gap will bite any future per-user feature (digests, notifications, billing seats) that starts from organizations.clerkOrgId.

Failure mode: SUCCESS: Claude shipped the smart engagement email engine (PR #186) by upgrading the existing re-engagement service instead of building a parallel system

Scope: agent:Claude

failure patterns

L046 MEDIUM OBSERVED ONCE 3x Moderate · 238t

WOA Lafayette runs their OWN call team, exactly like WOA China Grove. Exclude Lafayette from the CCM portfolio appointment rate, from uncalled/zero-dial alerts, and from every coaching recap. New leads with zero dials at Lafayette is EXPECTED, not a miss. Before flagging any project for zero dials, check it against the self-calling exclusion list (China Grove, Lafayette) and the Reporting-Active/Inactive status in Project Info.

Why: Coaching Amanda and Erica about leads they were never supposed to call destroys the credibility of the whole recap, and repeatedly surfacing a non-issue as the "one real issue" wastes David's attention every single morning. The China Grove precedent already existed; Lafayette was never added to it.

Failure mode: Arin/Dan flagged "WOA Lafayette: 3rd consecutive day of new leads with ZERO dials" as the day's one real call-center issue, and put it in the drafted team recap as something to tighten. It is not an issue at all.

Scope: agent:Arin

L047 MEDIUM OBSERVED ONCE 3x Moderate · 334t

WOA Yadkinville is NO LONGER CALLED by Sneeze It (David 2026-07-10). Treat it like ROT Frisco: excluded from the portfolio rate, from dial-volume trends, from drop-off alerts, and from every recap and DM. The deeper rule: a declining or zero dial count is NEVER evidence of a caller problem on its own. Before any project enters a recap as a "tighten" item, confirm it is Reporting-Active in Project Info AND not on the self-calling / no-longer-calling exclusion list. If a project's dials fall to zero, the FIRST hypothesis is that we stopped calling it, not that the callers slacked. When a correction removes one item, do not reflexively backfill the slot with the next-worst number to preserve a "3 wins / 3 tighten" shape -- a recap with two tighten points, or zero, is correct when that is the truth.

Why: Fabricating coaching points to fill a template destroys Amanda's and Erica's trust in every number Arin sends, and it burns David's attention twice: once to read it, once to correct it. The format is a container, not a quota.

Failure mode: After Lafayette was corrected, Arin/Dan immediately substituted "Yadkinville went from 17 dials Tuesday to 1 on Thursday" as a coaching point. Sneeze It is no longer calling Yadkinville at all. Two consecutive drafted recaps coached the team on projects they were never supposed to be dialing.

Scope: agent:Arin

operational heuristics

L048 MEDIUM OBSERVED ONCE 3x Moderate · 167t

Frame help/success/onboarding call copy positively: state plainly that the call is there to help and guide them, and describe what will actually happen on it (we'll walk through your setup, get you unstuck, answer your questions). Never say "this is not a sales call" or "no pitch" — describe the help, don't disclaim the sell.

Why: Defensive "not a sales" language triggers the exact suspicion it tries to defuse and undercuts a genuine help offer. David flagged this immediately.

Failure mode: Wrote a "customer success call" Calendly description that leaned on "no pitch, no slides" / not-a-sales-call framing. Protesting that it isn't a sales call makes it sound like one.

Scope: agent:Conatus

L049 MEDIUM OBSERVED ONCE 3x Moderate · 376t

Any script that answers "is anything missing / is everything covered?" must fail LOUD, never return an empty set as reassurance. Two rules: (1) assert the expected top-level key exists (`if 'data' not in resp: raise`) before computing a result; a zero/empty answer from a health check is a claim that must be proven, not a default. (2) Cross-check a zero result against one known-positive case before reporting it -- here, one direct call to a single account would have shown $57 of spend and exposed the lie instantly. Also: `~/.claude/meta-ads.sh accounts` exits 0 and prints nothing; do not build on it. Sweep with `/{business_id}/adaccounts?fields=name,account_status&limit=500` then batch `/{act_id}/insights` 50 at a time.

Why: "Nothing is wrong" is the single most dangerous output an audit can produce, because nobody investigates it. A silent empty result on a billing sweep means real revenue is never invoiced and nobody ever finds out. The failure mode is not a crash, it is confident silence.

Failure mode: SUCCESS: Claude caught a silent false-negative in a Meta billing sweep. Querying the Graph API adaccounts edge with nested field expansion (`fields=name,insights.date_preset(this_month){spend}`) returned an error payload with NO `data` key. The sweep script read it as an empty account list and confidently reported "0 accounts, $0.00 unbilled MTD spend" -- a clean bill of health that was entirely fabricated. Direct per-account queries then revealed 7 unbilled accounts spending $5,673 MTD.

Scope: agent:Dash