Seven-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, publish talk pages to a Jekyll shownotes site, and verify a recorded screencast against its storyboard. Includes a 113-entry Presentation Patterns taxonomy (83 observable: 64 patterns + 19 antipatterns; 30 unobservable: 21 patterns + 9 antipatterns) for scoring, brainstorming, and go-live preparation.
74
93%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
skills/vault-ingress/scripts/audit-source-identities.py is the networked,
read-only companion to the offline vault preflight. It asks yt-dlp for stable
provider metadata, compares that evidence with active talk records, and emits
review proposals. It never changes the tracking database or any vault artifact.
Run it after the offline structural preflight and before writing a source-repair plan:
"{python_path}" "{speaker_toolkit_root}/skills/vault-ingress/scripts/preflight-vault.py" {vault_root}
"{python_path}" "{speaker_toolkit_root}/skills/vault-ingress/scripts/audit-source-identities.py" {vault_root}The audit requires the pinned yt-dlp executable and network access. Executable
selection belongs to
skills/vault-ingress/scripts/ytdlp_runtime.py — resolve_ytdlp. An active
talk for this helper is a record with a nonempty video_url. Only supported YouTube
URL forms are fetched. The helper parses their 11-character IDs, groups every
record naming the same ID, and makes exactly one metadata request per group.
Records with a stored youtube_id but no active URL are not resurrected or
fetched; a rejected/cleared source stays inactive.
Stdout is the only output. The helper accepts a vault root or the database path:
"{python_path}" "{speaker_toolkit_root}/skills/vault-ingress/scripts/audit-source-identities.py" \
{vault_root}/tracking-database.jsonUse --captured-at <timezone-aware-ISO> only for a reproducible evidence run or
fixture. Normal runs stamp the current UTC time. Exit 0 means every requested
identity returned internally consistent metadata. Review findings such as title
mismatches, likely clips, and cross-talk collisions do not change that exit code.
Exit 1 means capture was incomplete or provider identity contradicted the
requested ID. Invocation errors exit 2.
The helper deliberately selects a small metadata subset:
{
"schema_version": 1,
"provider": "youtube",
"video_id": "AbCdEfGhI_1",
"title": "Title reported by YouTube",
"uploader": "Conference Channel",
"uploader_id": "@conference",
"upload_date": "2026-07-31",
"duration_seconds": 2700,
"webpage_url": "https://www.youtube.com/watch?v=AbCdEfGhI_1",
"webpage_video_id": "AbCdEfGhI_1",
"captured_at": "2026-07-31T19:00:00Z"
}These are provider facts, not delivery facts:
uploader/uploader_id identify the publishing account. They are never
copied to speakers and are not proof that the uploader spoke.upload_date is publication time. It is never copied to recorded_date and
does not establish when the talk was delivered.webpage_url is captured evidence of the fetched page. The audit never emits
a video_url repair or applies that URL to a record.Every successful talk audit carries this subset under
proposed_evidence.source_identity. It is evidence for review, not an apply
plan. Missing fields remain absent/null; the helper does not synthesize them.
A scan-shownotes.py conflict names a competing source for a talk that already
has one. Pass that report back to compare both sides through this auditor's
bounded fetching, stable evidence shape, redaction, and no-write guarantee,
instead of an ad hoc provider lookup outside the ingress workflow:
"{python_path}" "{speaker_toolkit_root}/skills/vault-ingress/scripts/audit-source-identities.py" \
"{vault_root}" --candidates-from "{scan_report_path}"Input. --candidates-from takes one scan-shownotes.py report path. See
skills/vault-ingress/scripts/audit-source-identities.py:
| What | Anchor |
|---|---|
| Accepted report generation | CANDIDATE_REPORT_SCHEMA_VERSION |
| Valid dispositions | CANDIDATE_DISPOSITIONS |
| Lanes with an auditable provider identity | CANDIDATE_LANES |
| Which reports and entries bind, and the finding each refusal emits | candidate_bindings() |
| Faults eligible to stay lane-local, and the code each takes | CANDIDATE_LANE_LOCAL_CODES |
Output. candidates[] carries provider_evidence and
active_provider_evidence in the same shape for field-for-field comparison,
plus same_source_as_active. sources[].lanes names which lane claimed each
fetched identity.
Candidate identities never enter the active-source assignment, so a candidate shared by two talks cannot appear as a collision between active identities.
Exit conditions. A refused report leaves candidates[] empty and the active
lane audited; the report's own findings name the refusal. A lane-local candidate
fault leaves the audit complete and the CLI exit clean. Every other fault
keeps its blocking code and fails the run.
Side effects. None. The audit writes nothing, and a candidate is never promoted or persisted here — reviewing this evidence and applying a decision are separate steps.
When both identities are valid uploads of the same delivery, review the two provider-fact blocks with independent event evidence and a recording/transcript comparison. Follow source-aliases.md to retain the inactive identity without rejecting it or replacing the canonical recording. An owner-approved official-upload switch uses the separate atomic promotion contract in that reference, not a repair followed by an alias append.
{
"schema_version": 4,
"captured_at": "2026-07-31T19:00:00Z",
"database": "/vault/tracking-database.json",
"complete": true,
"review_required": true,
"out_of_scope_talk_count": 0,
"active_talk_count": 2,
"unique_youtube_id_count": 1,
"metadata_fetch_count": 1,
"metadata_fetch_error_count": 0,
"metadata_unavailable_count": 0,
"candidate_count": 1,
"summary": {
"finding_count": 1,
"by_code": {"same_id_cross_talk_collision": 1}
},
"sources": [],
"talks": [],
"findings": []
}sources contains one record per fetched ID, with the sorted talk indexes and
filenames that caused the fetch, fetch_status, provider evidence, and any
error. fetch_status is ok, error, invalid, or unavailable.
metadata_fetch_error_count counts every status but ok and unavailable;
metadata_unavailable_count counts unavailable alone. talks contains one
record per active URL, its source_provider, its catalog comparison, and the
proposed evidence. out_of_scope_talk_count counts the active sources on a
supported provider this YouTube audit does not fetch from; those never set
review_required, because there is no fault to review. findings and summary.by_code are sorted; with the same
database, provider responses, and captured_at, the decoded JSON is identical.
Stable finding codes:
| Code | Meaning |
|---|---|
active_youtube_url_invalid | An active YouTube-looking URL has no valid ID |
active_video_provider_unsupported | Active URL names no supported provider at all; no fetch occurred |
active_source_provider_out_of_scope | Active URL is a supported non-YouTube identity this audit does not fetch; no fault, no review |
stored_youtube_id_mismatch | URL identity disagrees with stored youtube_id |
metadata_fetch_failed | yt-dlp was missing, timed out, failed, returned unusable JSON, or was refused access; retryable |
source_unavailable_upstream | The provider reports the recording itself is gone; not retryable and not blocking |
provider_video_id_mismatch | Returned provider ID differs from the requested ID; no proposal is emitted |
provider_webpage_identity_mismatch | Returned webpage names another ID; no proposal is emitted |
provider_metadata_incomplete | A stable capture field is absent/invalid |
provider_title_mismatch | Provider title lacks material full-title or explicit base-title agreement |
provider_event_mismatch | Provider title explicitly names a known event different from the catalog conference |
provider_duration_mismatch | Provider duration exceeds the audit's deterministic catalog tolerance |
provider_upload_predates_catalog | Upload date predates the cataloged delivery, compared at the catalog record's own precision |
stored_source_identity_differs | Fresh stable facts differ from an existing evidence block |
likely_non_delivery_clip | Conservative title/duration signals suggest a demo, teaser, excerpt, or other non-delivery artifact |
same_id_cross_talk_collision | One ID is active on records with materially different titles or delivery dates |
A refused fetch is classified before it becomes a finding. classify_fetch_failure
owns the decision; its two signature tables and their precedence are named at the
top of skills/vault-ingress/scripts/audit-source-identities.py.
source_unavailable_upstream is absent from ERROR_CODES, so an upstream loss
never sets complete: false. Recording it as a distinct code and status is what
stops a permanent loss from re-reading as a fresh high-priority fetch error on
every later run. Each finding carries evidence.retryable.
An unavailable source does not retract a claim already derived from it. Every
derived artifact stands on its own receipts — the local artifact's own digest,
and the provider evidence captured at the time of capture with its captured_at.
Neither is a live re-read of the provider, so neither weakens when the provider
stops serving the recording.
What is lost is forward capability, not past evidence: no re-verification against the provider, no re-download, and no fresh extraction for a recording held only upstream. A locally archived copy restores all three; without one, the derived artifacts are the only remaining record and must not be discarded to force a re-fetch.
Title and explicit-event comparison are separate: an abbreviated title cannot
waive a delivery's event identity. Their matching contract is owned by
skills/vault-ingress/scripts/source_identity_matching.py, which also owns the
catalog-date reading and the upload comparison this audit and preflight share —
see parse_catalog_date and upload_predates_catalog. A catalog record dated
YYYY is compared at year precision, never skipped, so this audit and the
preflight gate return the same verdict on the same record. The non-delivery
finding is a review signal, never an automatic rejection. Its conservative
signal combination is owned by
skills/vault-ingress/scripts/audit-source-identities.py in
_non_delivery_signals. Cross-talk collision findings include existing
source_relation values for human review.
source_rejections entry and explicit source clears. If it is correct, prepare
only the supported source_identity update.apply-source-repairs.py plan with exact old-value
preconditions. Dry-run first, then use --apply only after review.webpage_url into an unreviewed active URL.See source-identity-preflight.md for the persisted evidence contract, rejection ledger, duplicate relations, and guarded repair flow.
.tessl-plugin
rules
skills
illustrations
presentation-creator
references
patterns
build
deliver
prepare
scripts
screencast-recorder
shownotes-publisher
vault-clarification
vault-ingress
references
scripts
vault-profile