| name | workshop |
| description | Create an academic workshop presentation and speaker notes from a research paper. |
| hooks | {"PreToolUse":[{"matcher":"Read|Glob|Grep|Bash","hooks":[{"type":"command","command":"bun ${CLAUDE_PLUGIN_ROOT}/hooks/clarify-before-recon-guard.ts --workflow workshop"}]},{"matcher":"Edit|Write|MultiEdit|NotebookEdit|Bash|Agent|Workflow","hooks":[{"type":"command","command":"bun ${CLAUDE_PLUGIN_ROOT}/hooks/approved-artifact-gate.ts --workflow workshop"},{"type":"command","command":"bun ${CLAUDE_PLUGIN_ROOT}/hooks/orchestrator-mutation-guard.ts --workflow workshop"},{"type":"command","command":"bun ${CLAUDE_PLUGIN_ROOT}/hooks/workshop-phase-gate-guard.ts"},{"type":"command","command":"bun ${CLAUDE_PLUGIN_ROOT}/hooks/workshop-outline-executable-guard.ts"}]}],"PostToolUse":[{"matcher":"AskUserQuestion","hooks":[{"type":"command","command":"bun ${CLAUDE_PLUGIN_ROOT}/hooks/episode-phase.ts --workflow workshop"}]},{"matcher":"ExitPlanMode","hooks":[{"type":"command","command":"bun ${CLAUDE_PLUGIN_ROOT}/hooks/approved-artifact-persist.ts --workflow workshop"}]}]} |
Workshop
Announce: "I'm using workshop to create academic presentation slides and speaker notes."
Iron Laws
- NO GENERATION WITHOUT A RECEIPT-SELECTED, INDEPENDENTLY REVIEWED WORKSHOP PLAN.
- NO FIXED PLAN FILE OR PLANNING FRAGMENT AUTHORITY. Source Paper, Source Inventory, the seven-column Slide Spec, Outputs and Verification, and Review Surfaces live only in the authenticated generated PLAN.
- NO LLM OR DIRECTORY-DISCOVERY FALLBACK. Missing, stale, pending, conflicting, or malformed plan state blocks.
- NO SELF-REVIEW. Plan review, generation, verification, and human review remain distinct.
Write surface: main chat does not do the work
You may Write/Edit only under .planning/ and .claude/. Slides, notes, and every other
deliverable are written by a dispatched agent. orchestrator-mutation-guard is registered in this
skill's frontmatter, so the attempt is REFUSED, not corrected: a write you try anyway costs a turn
and produces nothing. Reach for Agent first, not after a denial. Bash is held to the same line โ
only the named read-only checks and compilers are permitted from main chat.
Two narrow exceptions: the generated plan while you are IN Plan mode, and .claude-workflows.json
when adopting governance.
Load constraints before implementation:
!bun ${CLAUDE_SKILL_DIR}/../../scripts/load-constraints.ts workshop
!bun ${CLAUDE_SKILL_DIR}/../../scripts/ensure-plans-directory.ts ${CLAUDE_SESSION_ID}
CLARIFY โ PLAN โ IMPLEMENT โ VERIFY โ REVIEW
Beats 3โ5 run as one program: workflows/work.js
Beats 3, 4 and 5 run as a single orchestrated workflow rather than three stretches of main-chat
discipline. Two steps, in this order.
Step 1 โ get the authenticated args. One call, and it is not optional.
bun ${CLAUDE_SKILL_DIR}/../../scripts/beat/work-args.ts <abs project> --workflow workshop --session ${CLAUDE_SESSION_ID}
It prints {projectDir, workflow, planPath, planHash} read from .planning/.state/review.json and
re-hashed against the plan's current bytes, or refuses and names the reason โ missing-artifact
(you have not been through PLAN), review-pending, stale-receipt (the plan was edited after
approval), or a receipt identity disagreement. Do not hand-copy planPath/planHash instead.
That is the step where a hash gets typed from memory and an unapproved plan gets implemented anyway.
Step 2 โ run the beats, merging in the task list.
Workflow({
scriptPath: "${CLAUDE_SKILL_DIR}/../../workflows/work.js",
args: { ...<the JSON from step 1, verbatim>, tasks: [{ id, name, work, writablePaths: [], acceptance }] },
})
work.js delegates IMPLEMENT to the workshop-generate workflow for this domain โ pass its inputs as
domainArgs and they are forwarded unread. A workshop-generate failure throws rather than silently
falling back to the generic per-task path, which would build slides and speaker notes by a route nobody reviewed.
It returns { workflow, planPath, planHash, overallPass, verdict, scoreTable, implemented, verified, findings, refutedFindings, reviews, tasksThatFlagged, carriedForward, domainRun }. Render the gate,
drive the fix loop from findings, and re-invoke with onlyChecks: tasksThatFlagged plus
priorReviews to re-judge only what flagged.
Why a program rather than three beats of instruction. The beat machinery restrains a free agent:
guards deny reconnaissance, the mutation guard denies main-chat writes, an order gate refuses an
out-of-order wave, a Stop hook refuses a turn end while review is owed. Each exists because the
orchestrator could do otherwise. A workflow script has no Write tool and no shell, so delegation is
structural and the beat order is the order of its statements. CLARIFY and PLAN approval stay above,
in main chat and hook-enforced, because both are conversations with a human that a subagent cannot
hold โ and work.js refuses to start without planPath and a 64-hex planHash, so it cannot be
used to skip them.
1. CLARIFY
Clarify paper, audience, duration, proportions, visual expectations, outputs, and review evidence.
Read ${CLAUDE_SKILL_DIR}/../beat-clarify/SKILL.md and follow it โ it owns the question set, the
stop condition, and how confirmed intent is carried forward as evidence. The
clarify-before-recon-guard hook enforces that clarification happens; the beat defines what it
is, which is why the gate alone was not adoption.
Gate: paper, audience, venue, duration, proportions, visual expectations, outputs, and review
evidence are explicit enough to enter native Plan mode without guessing.
2. PLAN
Read ${CLAUDE_SKILL_DIR}/../beat-plan/SKILL.md, then enter native Plan mode. The exact receipt-selected plan must contain these exact H2 headings:
## Presentation Intent
## Audience, Venue, Duration, and Proportions
## Source Paper โ source path and extracted metadata.
## Source Inventory โ complete F/T/R/A inventory.
## Slide Spec โ Slide | Section | Takeaway | Bullets | Inventory | Visual | Notes; every cell is required and Inventory has at least one declared F/T/R/A ID.
## Outputs and Verification โ section-granular Typst generation, compilation, constraints, semantic fidelity, and visual checks.
## Review Surfaces โ rendered deck and notes review.
After approval, retain the exact generated planPath and planHash; run ${CLAUDE_SKILL_DIR}/../workshop-plan-reviewer/SKILL.md. A fresh reviewer must make the receipt state APPROVED. Never choose a plan by listing .planning/ or infer a replacement name.
Gate: the receipt state is APPROVED for the exact generated planPath and planHash, set by a
reviewer session distinct from the approving session, and every required H2 heading is present with a
complete seven-column Slide Spec.
3. IMPLEMENT
NO WORKFLOW WITHOUT AN AUTHENTICATE PRE-STEP AND A --verify POST-STEP. Both
workshop workflow scripts are pure control flow โ the Workflow runtime forbids
import(), import.meta, process, and Buffer, so an orchestrator cannot open,
hash, or re-stat a file. Receipt/plan authentication and drift detection therefore
run in the deterministic authenticator on either side of every dispatch. They are
never delegated to an agent: asking a dispatched agent to vouch for its own inputs
is not authentication.
-
Compile the deterministic index in memory:
bun ${CLAUDE_SKILL_DIR}/../../scripts/workshop/workshop-slide-table.ts "<absolute project root>" --json
Require no violations, reviewStatus: "APPROVED", and the exact returned planPath and planHash.
-
Authenticate the receipt and the receipt-selected plan (pre-step). It snapshots
both under TOCTOU discipline โ O_NOFOLLOW open, fstat-vs-lstat identity
comparison before AND after the read, realpath containment, sha256 of the bytes
actually opened โ and rejects a symlinked .planning, .planning/.state,
receipt, or plan:
python3 ${CLAUDE_SKILL_DIR}/../../scripts/workshop/workshop_plan_auth.py \
--authenticate "<absolute project root>" --plan-hash "<index.planHash>" > /tmp/workshop-auth.json
Non-zero exit or ok !== true blocks generation โ read violations and stop. The
bundle carries projectReal, planPath, planHash, and artifacts, keyed
receipt and plan. ONE bundle serves both workflows; re-authenticate before
workshop-verify so its entry hashes describe the post-generation state.
-
Run the shared IMPLEMENT beat's pre-step. This is what binds each generating agent to the
fragment files it is allowed to write โ read ${CLAUDE_SKILL_DIR}/../beat-implement/SKILL.md
for the full contract. Build one task per SECTION from the index (id = section-<n>, matching
the TASK marker the workflow emits), plus one for the assembler:
echo "$PREFLIGHT_REQUEST_JSON" | bun ${CLAUDE_SKILL_DIR}/../../scripts/beat/preflight.ts
PREFLIGHT_REQUEST_JSON is {projectDir, workflow: "workshop", planReset: {planFile, planHash}, dispatchOwnership: "caller", readyWave: [...]}. Each section task declares
and the
same two as ; the assembler task () declares the deck and notes paths
โ writes a PDF beside each , and a
compile output nobody declared is an undeclared change, which adjudicates as a violation by an
agent that did exactly what it was told. Declare what the step actually writes, not just what you
think of as its deliverable.
4. VERIFY
Read ${CLAUDE_SKILL_DIR}/../beat-verify/SKILL.md. The verifier is never the generator.
- Verify the built deck independently โ re-authenticate first (IMPLEMENT step 2 again), then:
Workflow(name="workshop-verify", args={
"projectDir": "<absolute project root>", "projectReal": <bundle.projectReal>,
"pluginRoot": "${CLAUDE_SKILL_DIR}/../..",
"planPath": <bundle.planPath>, "planHash": <bundle.planHash>, "slideIndex": <parsed index>,
"artifacts": <bundle.artifacts>
})
The verifier enumerates built slides and makes the PLAN-to-slide join semantically, without injecting a candidate menu. It applies the parser's Source Inventory whitelist after the join.
- Finalize each return value (post-step). Both workflows return
verifyRequired: true
and driftVerified: false โ the verdict is provisional until the plan and receipt
are re-snapshotted against the entry bundle. Write the return value to disk and run:
python3 ${CLAUDE_SKILL_DIR}/../../scripts/workshop/workshop_plan_auth.py \
--verify /tmp/workshop-auth.json --findings /tmp/workshop-result.json > /tmp/workshop-final.json
If the plan or receipt moved during the asynchronous run, the post-step zeroes
finalPlanHash, prepends a critical artifact-integrity finding, and forces
overallPass: false with verdict: "ISSUES FOUND (artifact drift)". Drift means the
planning authority changed under the agents: re-authenticate and re-run, do not patch.
Read every gate from the finalized post-step output, never from the raw workflow
return: verifyRequired: true means the drift check has not run and the verdict is not
yet trustworthy.
If overallPass is false, fix reported findings and re-run selectively with the same path and hash. A replacement plan invalidates carry-forward review state.
Gate: the finalized post-step output reports overallPass: true with driftVerified and a
non-zero finalPlanHash matching the entry bundle, and no artifact-integrity finding is present.
5. REVIEW
Read ${CLAUDE_SKILL_DIR}/../beat-review/SKILL.md and record user dispositions in .planning/HUMAN_REVIEW.md. Route requested changes through ${CLAUDE_SKILL_DIR}/../workshop-revise/SKILL.md, which re-enters VERIFY on the same authenticated plan identity.
Gate: every disposition is recorded in .planning/HUMAN_REVIEW.md, the rendered deck and notes
the user inspected are the current build, and no REJECT: remains.
Deliverables
Typst deliverables remain presentation/slides.typ, presentation/notes.typ, and their rendered PDFs. Preserve F/T/R/A fidelity, seven-column Slide Spec semantics, unbiased joins, and both compile gates.