name: cascade description: "Post-session processing, v2. Six phases, one review gate at minute 3. Replaces the 15-step cascade. Triggered by Kathryn when she has a block — never scheduled, because a cloud routine cannot write to the mapped drive. Use when: user says cascade, run the cascade, process the session." metadata: version: "2.0.0" date: "2026-08-12" replaces: "session-intake, recap-json, recap-internal, update-cpm, update-advisory-record, update-projectplan, update-blueprint, update-roadmap, draft-actions, session-agenda, publish-to-drive, recap-email, cascade-report, update-board, cascade-cleanup" config: ".claude/cascade.config.json"
/cascade — v2
Design target: 15 minutes of Kathryn's time. 2 to approve a digest, 8 to read and send 2 emails, 5 to read one decision list. Anything that cannot justify itself against that budget does not run every session.
Triggered, never scheduled. She starts it when she has a block, because the run stops at phase 3 for her and a run that waits while she is away helps nobody.
(A cloud run can still publish — via the Google Drive connector, uploading true .docx with disableConversionToGoogleType, never a G: mount. What it cannot do is wait for her. That is the reason, not the drive.)
Client-specific values — repo paths, drive root, client and advisor names, the initiative list — live in .claude/cascade.config.json. Nothing in this file is Elite-specific. Read the config first.
0 · Repo binding — read before anything else
This skill exists in identical copies in every engagement repo. The Skill tool may load any of them. On 2026-08-17 it was invoked from aos-client-rc and loaded the copy in aos-client-jb. The copies were byte-identical, so nothing broke — but nothing except luck stopped it.
The rule that makes which-copy-loaded irrelevant:
The directory this skill file was loaded from is NEVER a path root. Every path — config, transcript, ledgers, qc scripts, drafts, archive — resolves from the current working directory, not from the skill's base directory.
Do this first, before phase 1, every run:
pwd. That is the engagement repo. Nothing else is.- Read
.claude/cascade.config.jsonfrom that path. If it is missing, STOP — this repo is not ported to v2. Do not fall back to another repo's config; a config carries client names, recipient addresses and a drive root, and borrowing one sends a client's recap to a different client. - Check
config.clientagainst the repo. If they disagree, STOP and say so. - If the skill's base directory is a different repo than
pwd, note it in the handoff. Do not treat it as fatal — note it, pin every path topwd, continue.
Never read a transcript, ledger, or last-sent record through a path that starts at the skill's base directory. That is the one mistake that would cross two clients' data, and it is silent.
Run this forked, not inline. Spawn it as its own agent and let it work; do not execute it turn-by-turn in a conversation that is also doing other work. On 2026-08-17 it ran inline three times: it stalled four hours at the gate while the conversation moved to email copy, phases 4-6 were never reached until Kathryn asked where they were, and the digest sat unread in the repo because the run had lost the thread. A forked run finishes its phases regardless of what the conversation is doing and hands back one complete package.
The gate still belongs to Kathryn — the fork stops at phase 3 and reports, same as inline. Forking changes who is holding the thread, not who approves.
0.5 · What produces what — read before writing anything
The renderers are the author. You are the data-entry and judgment layer.
This is the rule the 2026-08-17 run broke. That run hand-wrote the digest and the recap, invented sections that had never appeared in a sent email, and shipped a recap Kathryn described as unreadable. Every producer it needed already existed in qc/ and went unused.
| Artifact | Produced by | You supply |
|---|---|---|
sessions/recap- | you — the only thing you author | structured, cited, judgment calls marked |
| The digest | qc/render_digest.py | nothing — it renders |
| The client recap email | qc/render_recap.py | nothing — it renders |
| The CPM, Advisory Record, plans, blueprint, roadmap | /render | nothing — they are views |
render_recap.py's own docstring states the reason: "The recap was the last load-bearing document still produced by a prompt that re-read the JSON and rewrote it from scratch every Monday. That is untestable by construction: same input, different output, and the only way to find out it was wrong was to ship it."
Hand-authoring any client-facing artifact is a failed run, even if the prose is good. Same JSON in, same HTML out, or the shape gate has nothing to check.
Before phase 1, run ls qc/. Anything named render produces an artifact and anything named verify checks one. If a phase below tells you to "write" something and a renderer exists for it, the renderer writes it and you write its input.
Phase 1 · Intake
Both halves. Skipping the second caused two errors on 8/11.
- The room. Transcript from Otter. If the API serves metadata but not the body, that is a known per-recording failure — go straight to manual export from the Otter web UI, do not retry four times.
- Since the room. Sweep the inbox from session start to now. Anything the client sent after the session outranks the transcript. The transcript does not know what happened next.
- Speakers. If the transcript leaves anyone unlabelled, write the attribution map before anything quotes a line. Otter labelled neither of two participants on 8/11 and split one thought across two speaker labels.
Write sessions/session-state-. Never overwrite a state file written mid-session by a pre-fetch — replace it, and say so.
Phase 2 · Digest
Produced by qc/render_digest.py from sessions/recap-. You write the JSON, not the digest.
One page. This is the source every other output derives from, so it is the only thing that has to be right.
Contents: what was decided · what is open · who owes what · every judgment call made in phase 1.
All gates run here, on the source, before anything derives from it:
| Gate | Catches |
|---|---|
qc/verify_claims.py | Fabricated quotes and uncited actions, this session |
qc/verifypriorclaims.py | Claims about prior sessions. The gap that cost an evening |
qc/verify_hedge.py | Unhedged assertion over hedged source |
qc/verifyconstraintschema.py --strict | Vocabulary and reference integrity |
qc/verify_currency.py | Living docs that aged because a step was held |
qc/verify_overstatement.py | "Still shaping" rendered under "Decided" |
qc/verifycoverage.py · verifyparity.py · verify_structure.py | Completeness and shape |
qc/reference_diff.py | New proper nouns |
qc/verifyrecipients.py · verifyvoice.py · verify_codify.py | Outbound |
qc/preflight.py is the exit condition. Its own docstring: "the run does not hand Kathryn anything until this exits 0." Built 2026-08-10. It did not run on 8/11, and the run was reported as gates-CLEAR on 5 of 14 checks.
The full list lives in .claude/cascade.config.json under gates. Read it and run every entry. Remembering which gates to run is exactly what failed.
Fail-closed. A blocked run beats a wrong document.
Phase 3 · The gate
Print the digest. Stop. Wait.
This is the only stop in the run. Two minutes of her attention here buys correctness in everything downstream — the alternative is what happened on 8/11, where one wrong fact at phase 2 was copied into 6 files before anyone read it.
She corrects or approves. After that, no more questions until the run ends.
Phase 4 · Send
The two things she actually uses. Nothing else is written in this phase.
- Client recap email — rendered by
qc/renderrecap.py, never written by hand. Thenqc/verifyshape.py— the section spec comes from an email Kathryn actually sent, and a difference is either a deliberate change you state or drift you fix. Thenqc/last-sent- .json cross-client-check, thenkathryn-email-voice, in that order, both required. Put the rendered body into the Gmail draft — do not retype it. - Next session's agenda — her intelligence brief, internal.
Drafts only. Never send.
Phase 5 · Ledgers and publish
- Merge the session delta into
constraint-state.jsonandengagement-ledger.json. Every changed item gets both registers written — see/render. - Publish only what changed to the drive. Requires the desktop bridge; if it is not there, skip and say so rather than failing.
No document regeneration. The CPM, Advisory Record, project plans, blueprint and roadmap are views. They render on demand — /render — not on a schedule.
Phase 6 · Handoff
Written incrementally from phase 1, not assembled at the end. Every phase appends its own item as it makes the call, so the report is complete the moment the run ends and survives a window closing mid-run.
Three sections:
Needs your eyes — every judgment call, marked.
Results — only against decisions Kathryn made. Never a date counter.
READY, NOT YET SHOWN items she tested and meant to ship, that missed a session
DELIVERED, NO RESPONSE shipped, no client reaction by the next session
ROLLED 3+ TIMES asked for repeatedly — a delivery-method signal
Items in state built (she has not tested it) or parked (she decided, with a reason) report nothing. Not ready in her eyes means not ready; parked means she already made the call. A gate that reports a deliberate decision as a failure is noise, and she has enough.
Open decisions — anything that needs her and is not urgent.
Rules
- One gate, phase 3. Self-advance everywhere else. Do not ask "should I continue."
- When a step needs judgment, make the best-supported call, mark it in the handoff, and keep going.
- Every claim about a prior session carries a transcript filename and a timestamp, or it does not get written. This is the rule the 8/11 run did not have.
- Client-of-client names may be recorded only as an instance of a named client capability problem, never as a thread of their own. No parent problem, no entry.
- Write incrementally. If the window closes mid-run, everything done so far is already in the right place.
- Never send an email. Draft only.
What v1 did that v2 does not
| Dropped | Why |
|---|---|
recap-internal | Duplicated the digest |
update-board | Writes to Kathryn's own board, not a client's |
cascade-cleanup | Moved files between folders to solve a problem nobody reported |
| action-drafts summary file | Duplicated the handoff |
| Per-session regeneration of 5 living docs | They are views. /render |
| The 10:16 routine | Triggered now. The routine pre-fetches and stops |