Six-skill presentation system: ingest talks into a rhetoric vault, run interactive clarification, generate a speaker profile, create presentations that match your documented patterns, produce the deck illustrations + thumbnail visual layer, and publish talk pages to a Jekyll shownotes site. Includes a 102-entry Presentation Patterns taxonomy (91 observable, 11 unobservable go-live items) for scoring, brainstorming, and go-live preparation.
86
92%
Does it follow best practices?
Impact
86%
1.24xAverage score across 26 eval scenarios
Advisory
Suggest reviewing before use
NEVER call the qrcode library directly or generate QR images through any
other means. ALWAYS use generate-qr.py. The script handles URL shortening,
custom back-half, tracking DB updates, color matching, and secrets.
When the target is not a .pptx deck (e.g., presenterm, PDF, or standalone PNG),
use --png-only mode:
python3 generate-qr.py --png-only --talk-slug SLUG --shownotes-url URL \
--output /path/to/qr.png --bg-color "128,0,128"The short link's back-half MUST ALWAYS be the talk slug — the bit.ly custom
back-half AND the rebrand.ly slashtag, with no override. When a custom domain is
configured in the vault profile (bitly_domain / rebrandly_domain), the short
link MUST use it. The script does this automatically: --talk-slug devnexus26-robocoders with bitly_domain: jbaru.ch creates
jbaru.ch/devnexus26-robocoders (not bit.ly/a3xK9f). If the slug back-half
can't be set, the script fails to a raw-URL fallback rather than keeping a random
hash.
Random hashes are untraceable and unprofessional. The back-half IS the slug.
The QR code MUST encode the bit.ly/rebrandly URL, never the raw shownotes URL. The shortener is the decoupling layer — if the shownotes URL changes later, update the shortener target, and every printed QR code stays valid.
The only exception is "shortener": "none" (explicit opt-out), where the raw
URL is the only option.
The back-half IS talk.slug — composed and agreed with the author in Phase 1
(per the speaker's slug_convention.template) and persisted in outline.yaml /
presentation-spec.md. The QR step uses it VERBATIM: never invent, rephrase,
re-derive, abbreviate, or date-prefix it. The back-half must equal the published
shownotes slug.
devnexus26-robocoders, not 2026-04-16-devnexus-robocoders)When the speaker profile has no shortener configured (key missing, not set
to "none"), STOP and ask the user to choose one.
"shortener": "none" → explicit opt-out, proceed without shorteningshortener key missing → NOT CONFIGURED → ask before proceedingSilent generation with a raw URL when shortening was never discussed = failure.
If secrets.json is missing or lacks the required API token, STOP and guide
the user to create it. Do not silently degrade to a raw URL.
The script prints actionable creation commands — but the agent must treat a missing token as a blocker, not a fallback trigger.
The first time a short link is created for the active shortener, the custom-domain
decision MUST be recorded in the vault profile. Three states of
publishing_process.qr_code.{shortener}_domain:
jbaru.ch) and SAVE the answer before the link is created.null → recorded decision: no custom domain, use the shortener default (bit.ly).Save the decision either way — the domain string, or null for "no custom domain".
A null is a recorded decision, not an absent value; never re-ask once saved. On
the Direct API path generate-qr.py STOPS when the key is absent; on the MCP path
the agent makes the same check before resolving the link.
A deck adapted (trimmed) from another talk carries that talk's QR images. The QR step detects every existing QR — the closing slide AND any earlier shownotes slide — and replaces it in place at the same position and size, never adding a second QR beside it.
Detection is by CONTENT, not size: an inherited QR can be any size (the same QR
may appear at 1.8" and 2.8"), so a size band misses it. A QR is a square picture
that is both ~2-color and roughly balanced between those colors — which excludes
colored diagrams (many colors) and mostly-one-color text screenshots (unbalanced).
This runs in generate-qr.py (find_qr_rects), which can read pixels; it hands
the matched geometry to the InsertQR macro (RunDeckOps.bas), which can't run
image libraries and just removes those exact shapes and places the QR there. The
thresholds are named in generate-qr.py.
.github
eval-resources
humor-postmortem-blind-spots
qr-bitly-slug-from-outline
qr-missing-shortener-detection
shownotes-publisher-omit-placeholder
shownotes-publisher-publish-no-date
shownotes-publisher-publish-with-date
shownotes-publisher-update-add-video
video-extraction-diagnostics
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10
scenario-11
scenario-12
scenario-13
scenario-14
scenario-15
scenario-16
scenario-17
scenario-18
scenario-19
scenario-20
scenario-21
scenario-22
scenario-23
scenario-24
scenario-25
scenario-26
rules
scripts
skills
illustrations
presentation-creator
references
patterns
build
deliver
prepare
scripts
shownotes-publisher
vault-clarification
vault-ingress
vault-profile
tests