# Lifecycle marketing audit: <programme name>

## Header

- Programme: <product or brand>, business model <saas | ecommerce | app | leadgen>
- Senders in scope: <platform, workspace or project, region, channels, purpose, owner> (one bullet each)
- Senders found outside stack.md: <from headers, DMARC reports or Postmaster, or "none">
- Regions and channels: <list>
- Depth: <Scan | Full | Focused: areas>
- Windows: activity <YYYY-MM-DD to YYYY-MM-DD>; imports and preference changes <90-day range>; holdout since <date of last assignment change>
- Read time: <YYYY-MM-DD HH:MM UTC>
- Access per sender: <MCP server and mode, export, dashboard read>, scopes <list>
- Scripts: <ran with the commands in the appendix | not run, rules applied by hand because ...>
- Inputs used: <martech-context files read, exports, dashboards, decisions cited>

## Scorecard

- Journey coverage: <n> FAIL, <n> WARN, <n> PASS, <n> NOT CHECKED. Top finding: <one sentence>
- Triggers and event data: <counts>. Top finding: <sentence>
- Segments: <counts>. Top finding: <sentence>
- Frequency caps and suppression: <counts>. Top finding: <sentence>
- Preferences and consent: <counts>. Top finding: <sentence>
- Deliverability and authentication: <counts>. Top finding: <sentence>
- Measurement and holdouts: <counts>. Top finding: <sentence>
- Gap list: <n> P0, <n> P1, <n> P2, <n> P3

## P0 alerts raised during the audit

- <time UTC> <rule IDs>: <finding>. Evidence: <reference>. Drafted containment: <pause of the journey or sync field>. Told: <user and owner role>. Owner decision: <approved | pending | declined>

## Top gaps (P0 and P1)

- <gap ID> <priority> <rule IDs>: <finding>. Evidence: <short reference>. Change request: <CR ID>. Owner: <role>

## Findings by area

### Journey coverage (JC01 to JC09)

- <LEVEL> <rule> <journey name> [<ID>]: <finding>. Evidence: <script line, configuration quote, query>. Confidence: <confirmed | configuration-only | unconfirmed>. Seed: <result or "not run" with reason>

### Triggers and event data (TD01 to TD08)

- <same format>

### Segments (SG01 to SG06)

- <same format>

### Frequency caps and suppression (FC01 to FC09)

- <same format>

### Preferences and consent (PC01 to PC10)

- <same format>

### Deliverability and authentication (DL01 to DL17)

- <same format, one group per sending stream>

### Measurement and holdouts (MH01 to MH10)

- <same format>

## Coverage map

- By type: <required | recommended> <journey type>: <journey IDs and senders, or MISSING, or N/A with reason>
- By stage: <onboarding | activation | conversion | adoption | retention | expansion | winback | service>: <live and external journey IDs, or none>. Missing required: <types>. Missing recommended: <types>
- Coverage ratio <journey ID>: <entries> of <expected> = <ratio>, source query <reference>
- Sending check (JC09) <journey ID>: <entries>, <sends> sent, <steps not sending> steps not sending, status read <date>

## Message pressure summary

- Recipients in the log: <n>. Peak per recipient in 24 hours: p50 <n>, p90 <n>, max <n>. In 7 days: p50 <n>, p90 <n>, max <n>
- Over the policy: <n> in 24 hours, <n> in 7 days; cross-sender cases <n of m>
- Keys shared with the send log: <n of m preference-log profiles>, <n of m holdout members>; topic scopes NOT CHECKED: <topic IDs, or none>
- Sends after opt-out: <n> FAIL (more than 48 hours, or after a stale write), <n> slow (1 to 48 hours, PC03), <n> in flight (within 1 hour); texts after opt-out: <n> marketing, <n> of other classes after STOP; suspected stale writes: <n>
- Holdout contamination: <n> sends while assigned (membership dates given: <yes | no>); quiet hours: <n>
- Journey pairs within 24 hours: <pair: profiles>

## Deliverability per stream

- <stream>: From <address and domain>, Return-Path <domain>, DKIM d= <domain> s= <selector>; receiver results from <authserv-ids, or "none written" for Microsoft>; dmarc=<result>; one-click <PASS | FAIL: reason>; body link <found | preferences only | missing>, login asked <yes | no>, pages <n>; TLS <yes | no>
- <stream>: provider replies in 30 days <provider, code, count; or "none">; blocklist lookups <operator, item (brand-owned, dedicated or shared), listed | not listed, date, delisting route>; shares From address or IP with <other stream, or "none"> (DL17)
- <primary domain>: bulk status <Gmail yes | no, Microsoft yes | no (5,000 a day)>; Postmaster compliance <values, read date>; spam rate <values, dates UTC>; hard bounce rate <value, denominator>

## Measurement claims and holdouts

- Claim: "<as reported>". Method: <attribution model and window | holdout | test>. Senders whose credit is summed: <list; overlap share after deduplicating by order or conversion ID>. Verdict: <credit, not incremental | credit double counted | supported | not proven | invalid because ...>
- Holdout <name>: unit <person | account>, size <n and %>, senders that exclude it <list>, contamination <n>, SRM p <value and test>, MDE <pp> against decision threshold <pp>, readout <unpooled interval | NOT RELIABLE: score interval and Fisher p>

## Not checked

- <rule or area>: <reason, for example "no SMS sender" or "no access to Yahoo complaint feedback">

## Seed test evidence

- <seed ID> <rule>: <setup, action, expected, observed, timestamps with timezone, records created, approved by, run by>

## Decisions needed from owners

- <question>: <owner role>, needed by <date>, blocks <gap IDs>

## Proposed martech-context updates

- <file>: <proposed addition or change>. Status: proposed, not written

## Access and calls log

- <time UTC> <tool or export> <read call or file> <scope or mode>
- Write calls: none outside approved seed tests (each listed with its approval and who ran it)

## Appendix: script outputs

For each script: the exact command, the input files with their row counts and windows, the summary line and the exit status. Paste the FAIL and WARN lines the findings cite. Input files hold internal IDs or salted hashes only.

- inventory_audit.py: <command>. Summary: <N FAIL, N WARN, N PASS, N INFO>. Exit <n>
- message_pressure.py: <command>. Summary: <N FAIL, N WARN, N PASS>. Exit <n>
- check_message_headers.py: <command, one file per stream>. Summary: <N files: N FAIL, N WARN, N PASS>. Exit <n>
- holdout_math.py: <plan and result commands>. Key lines: <MDE, interval, SRM p>. Exit <n>
- gap_list_check.py: <command>. Summary: <N rows, N ERROR, N NOTE>. Exit <n>
- Not run: <script and reason, and how the rule was applied by hand>

## Next step

- Gap list: <path to the CSV>. Change requests: <path>. Seed test plan: <path>.
- No configuration was changed by this audit; approved seed tests created only the records listed under Seed test evidence.
