# Session handoff
Update this at the end of every session. Keep it to what the next session
can't infer from `progress.md` + `feature_list.json`.
## State at last handoff
- Full harness built: `AGENTS.md`, `feature_list.json`, `init.sh`,
`verify_email_marketing.py`, `samples/good/welcome-sequence.md`,
`samples/bad/welcome-sequence.md`, `progress.md`, this file.
- All 9 playbooks already existed in `playbooks/` from a prior session โ
do not recreate them; read them before building any deliverable.
- `MANUAL.md` (42KB, complete) is the deep knowledge; do not duplicate its
content into playbooks/AGENTS/deliverables โ cite section numbers instead.
- Only `welcome-sequence` has a real passing artifact (the good sample).
The other five feature types are `todo` โ the linter logic for all of
them exists and was smoke-tested inline (not as saved evidence) for
`daily-email` and `deliverability-audit`; treat that as unverified until
a real `workspace/` artifact passes.
## What the next session should do first
1. Read `progress.md`, then `feature_list.json`.
2. Run `./init.sh` โ confirm it still passes (good sample passes, bad sample fails).
3. Pick any `todo` feature (all five are independently startable โ no
dependency chain blocks them) and build a real `workspace/<feature-id>.md`
artifact, following the field format demonstrated in
`samples/good/welcome-sequence.md` and the parser logic in
`verify_email_marketing.py`.
## Gotchas / notes
- **Frontmatter is mandatory.** Every deliverable file needs
`---\ntype: <deliverable-type>\n---` at the very top or the linter fails
immediately with "no frontmatter type found." The type must be one of:
`welcome-sequence`, `launch-sequence`, `ecom-flow-set`, `daily-email`,
`reactivation-campaign`, `deliverability-audit`.
- **CTA link counting is by distinct URL, not by raw markdown-link count.**
Repeating the same link twice in an email body (once in the CTA field,
once inline in prose) is fine โ that's reinforcement, not multi-CTA. Two
*different* destinations in one email is the actual violation (Fogg:
one prompt, one action). See `distinct_link_targets()` in the linter.
Get this wrong and you'll either under- or over-fail real drafts.
- **`## Email N` / `## Flow: <name>` headers are the block boundaries** the
parser splits on. Everything between one heading and the next (or EOF)
belongs to that block; fields are `Key: value` lines until a `Body:`
marker, after which everything is free-text body.
- **`deliverability-audit` uses a markdown table, not `## Email N` blocks** โ
rows must be `| Item | [status] | Evidence |` with a real evidence string
in the third column. A `[verified]` status with an empty or `โ` evidence
cell fails the linter on purpose.
- **The house-voice banned-vocabulary list lives in two places** and must
stay in sync if either changes: `~/.claude/skills/brand-bible/skill.md`
("Absolute forbiddens" table) and `BANNED_VOCAB` in
`verify_email_marketing.py`. Only `daily-email` enforces it today.
- **`./init.sh` runs the WHOLE gate on purpose** โ every sample in both
`samples/good/` and `samples/bad/` is checked every run. Don't let a new
sample silently break the anti-theater proof.
## Open questions for the user
- Whether to add good/bad sample pairs for the remaining five deliverable
types (currently only `welcome-sequence` has a proof pair) โ the linter
logic exists for all six but only one is demonstrated end-to-end.
- Whether `deliverability-audit` should be built now against the *real*
19Keys Resend domain (mostly `[todo]` honestly) or left as a template
until `owner-action-chaser` clears the CAN-SPAM postal-address P0.