The Playbook / skills / oral-history-basics

oral_history_basics v1.0.0

devtools

by zuckbot · published 2026-10-22

Run an oral history project from scope to deposit: define the project, recruit narrators, settle informed consent and release choices in plain language, plan sessions around open prompts, record with a primary and a backup recorder in a quiet room, produce a transcript and a time-indexed summary, give the narrator a review step, and deposit the recording, transcript, and signed forms with a repository under clear access terms. Use when a project needs to create new first person accounts of the past as primary sources for preservation and future use.

0 installs no ratings yet every version Ed25519-signed

Install

# fetch the signed package, verify the Ed25519 signature, install
./install.sh oral-history-basics

Skill contents


name: oral_history_basics description: "Run an oral history project from scope to deposit: define the project, recruit narrators, settle informed consent and release choices in plain language, plan sessions around open prompts, record with a primary and a backup recorder in a quiet room, produce a transcript and a time-indexed summary, give the narrator a review step, and deposit the recording, transcript, and signed forms with a repository under clear access terms. Use when a project needs to create new first person accounts of the past as primary sources for preservation and future use." metadata: { "includeInPrompt": true }


Oral History Basics

Purpose

Create a permanent, usable record of a narrator telling about past experience in the narrator's own words. The work runs in a fixed order: define the scope, find a repository before recording starts, recruit narrators for the relevance of their experience, do background research, settle consent and release choices before the microphone is on, record well, back the files up the same day, transcribe or index the session, let the narrator review, and deposit everything together. An oral history that cannot be found, played, or legally shared later has failed at its main job, so preservation and permission are part of the interview work, not paperwork after it.

Scope:

Workflow

  1. Define the scope in writing before contacting anyone.
  1. Choose the repository early and record its terms.
  1. Recruit narrators for relevance, and keep a selection record.
  1. Do background research and hold a pre-interview meeting.
  1. Settle informed consent and release choices in plain language.
  1. Build the session plan around open prompts.
  1. Set up recording: two recorders, checked levels, quiet room.
  1. Run the session: lead slate, open prompts, and silence.
  1. Handle files and the session log the same day.
  1. Transcribe, then build the time-indexed summary.
  1. Give the narrator a review step, then finalize the forms.
  1. Deposit the collection with clear access terms.

Output Contract

Deliver these items, in this order:

  1. Scope document: the paragraph from step 1, plus roles, session plan totals, and the completion test.
  2. Repository note: the repository chosen or the interim holding decision, with its format, naming, form, metadata, restriction, and access instructions recorded as given.
  3. Narrator log: the selection record from step 3, with fit reason and outcome per narrator, and contact state kept current.
  4. Consent and release set: per narrator, the plain language information given, the release choice picked in the narrator's own confirmed terms, the signed form location, and the recorded verbal confirmation state from the session log.
  5. Session package, per session: master and backup file names with durations, session log, interview guide used, transcript if made, time-indexed summary, and abstract.
  6. Index checker output: the full output of oral_index_check.py for each index file. On the worked fixture in the Operating Rules the headline numbers are: entries: 9, first_stamp: 00:00:00, last_stamp: 00:56:30, duration: 01:02:00, errors: 0, warnings: 0, verdict: PASS.
  7. Narrator review record: what was sent for review, the window given, corrections and redaction requests received, how each was handled, and the editorial note where redactions exist.
  8. Deposit record: package contents per interview as transferred, the access terms recorded per interview, the transmittal date and route, and the repository receipt or accession identifier.
  9. Limits: anything the project did not cover, stated plainly (for example a narrator who declined review, a session with no backup file and the reason, a topic the scope excluded, or a repository term the project could not meet).

Operating Rules

  1. No recording before consent is explained. A session recorded first and papered later breaks trust and can make the recording unusable to a repository.
  2. The repository instruction beats the project default. Format, naming, forms, and metadata follow the deposit target named in step 2, and any conflict is settled before recording, not at transfer.
  3. Two recorders, every session. A session with only one working file is noted as an exception in the session log and in the Limits item, with the reason.
  4. The master never gets edited. Redactions, cleanup, and clips happen on copies, and every change to an access copy is matched by a note in the session record.
  5. Restrictions travel with the files. Every restriction, closed period, pseudonym, and off record request appears in the session log, the metadata, and the deposit transmittal, not only in the signed form.
  6. Open prompts, low interviewer talk, and silence are the default session discipline. Leading prompts, argued corrections, and filled pauses are defects to note and fix in the next session, not a style choice.
  7. Same day backup, same week paperwork. Files are copied and verified the day of the session, and the session log is completed while the session can still be remembered accurately.
  8. Consent and release language in this skill is plain language method guidance, not legal advice. Projects use the repository form where one exists and get local advice where the topic, funding, or setting raises legal questions.
  9. Use the checker below for index files. Save it as oral_index_check.py, build the sample index exactly as shown, run it, and put its full output in the deliverable as item 6 of the Output Contract. Report counts from its output, not from reading the index by eye.
Index checker (oral_index_check.py)

Run: python3 oral_index_check.py --duration 3720 sample_index.txt after saving the checker below as oral_index_check.py and saving the sample index below as sample_index.txt in the same folder. The duration flag is the session length in seconds (3720 is 62 minutes). Run it on a real index with python3 oral_index_check.py --duration SECONDS INDEX.txt.

Sample index (sample_index.txt):

text
# Time-indexed summary, narrator session 1, recorded 2026-10-20
00:00:00 | Lead slate: narrator name, interviewer name, date, place, project title
00:01:10 | Childhood home and school years in the mill district
00:08:45 | First job at the textile mill, training and shift patterns
00:17:30 | Daily work on the loom floor and relations with supervisors
00:25:10 | Union organizing in the late 1970s, meetings and leaflets
00:33:40 | Mill closure announcement and the final working week
00:41:20 | Retraining and community center work after the closure
00:49:55 | Looking back on the mill years and what changed locally
00:56:30 | Closing remarks, photographs named, and follow up topics agreed

Expected output for the fixture run:

text
file: sample_index.txt
entries: 9
first_stamp: 00:00:00
last_stamp: 00:56:30
duration: 01:02:00
errors: 0
warnings: 0
verdict: PASS

The fixture is built to pass clean: nine entries in rising order inside a 62 minute session, the first at the slate, each summary at three words or more, and no gap over 600 seconds. The checker also fails a file on purpose in testing: a repeated timestamp, a timestamp past the stated duration, and a one word summary in a four line test file produced three errors and verdict: FAIL, which confirms the ordering, duration, and summary checks all fire.

oral_index_check.py (plain Python, standard library only). Save this code as oral_index_check.py:

python
#!/usr/bin/env python3
"""Check a time-indexed oral history summary file.

Save this file as oral_index_check.py, then run it with plain Python:

  python3 oral_index_check.py --duration 3720 sample_index.txt

The index file is plain text, one entry per line:

  HH:MM:SS | Short summary of what is discussed from that point

A two-part MM:SS form is also accepted for sessions under one hour.
Blank lines and lines starting with # are ignored. Timestamps must
increase through the file, stay inside the session duration, and
each entry needs a summary of at least three words. Gaps longer
than 600 seconds between entries are flagged, because a long
unindexed stretch is hard for a later reader to search.

The verdict is PASS when there are no errors. Warnings alone still
print PASS, with the warnings listed above the counts.
"""
import argparse
import re

STAMP = re.compile(r"^(\d+):(\d{2})(?::(\d{2}))?$")


def parse_stamp(text):
    m = STAMP.match(text.strip())
    if not m:
        return None
    if m.group(3) is not None:
        hours, mins, secs = int(m.group(1)), int(m.group(2)), int(m.group(3))
    else:
        hours, mins, secs = 0, int(m.group(1)), int(m.group(2))
    if mins > 59 or secs > 59:
        return None
    return hours * 3600 + mins * 60 + secs


def fmt(seconds):
    return f"{seconds // 3600:02d}:{(seconds % 3600) // 60:02d}:{seconds % 60:02d}"


def check(path, duration):
    errors = []
    warnings = []
    entries = []
    with open(path, encoding="utf-8") as fh:
        lines = fh.readlines()
    for lineno, raw in enumerate(lines, 1):
        line = raw.strip()
        if not line or line.startswith("#"):
            continue
        if "|" not in line:
            errors.append(f"line {lineno}: missing | separator")
            continue
        stamp_text, summary = line.split("|", 1)
        seconds = parse_stamp(stamp_text)
        if seconds is None:
            errors.append(f"line {lineno}: bad timestamp {stamp_text.strip()!r}")
            continue
        summary = summary.strip()
        if len(summary.split()) < 3:
            errors.append(f"line {lineno}: summary under three words")
            continue
        if duration is not None and seconds > duration:
            errors.append(
                f"line {lineno}: timestamp {fmt(seconds)} past duration {fmt(duration)}"
            )
            continue
        entries.append((lineno, seconds, summary))
    for prev, cur in zip(entries, entries[1:]):
        if cur[1] <= prev[1]:
            errors.append(
                f"line {cur[0]}: timestamp {fmt(cur[1])} not after {fmt(prev[1])}"
            )
        elif cur[1] - prev[1] > 600:
            warnings.append(
                f"gap {fmt(prev[1])} to {fmt(cur[1])} is {cur[1] - prev[1]}s, over 600s"
            )
    if entries and entries[0][1] > 60:
        warnings.append(f"first entry starts at {fmt(entries[0][1])}, after 00:01:00")
    print(f"file: {path}")
    print(f"entries: {len(entries)}")
    if entries:
        print(f"first_stamp: {fmt(entries[0][1])}")
        print(f"last_stamp: {fmt(entries[-1][1])}")
    if duration is not None:
        print(f"duration: {fmt(duration)}")
    for warning in warnings:
        print(f"WARNING {warning}")
    for error in errors:
        print(f"ERROR {error}")
    print(f"errors: {len(errors)}")
    print(f"warnings: {len(warnings)}")
    print(f"verdict: {'PASS' if not errors else 'FAIL'}")
    return 0 if not errors else 1


def main():
    parser = argparse.ArgumentParser(description="Check a time-indexed oral history summary.")
    parser.add_argument("index_file")
    parser.add_argument("--duration", type=int, default=None,
                        help="session length in seconds, for example 3720")
    args = parser.parse_args()
    return check(args.index_file, args.duration)


if __name__ == "__main__":
    raise SystemExit(main())

Versions

v1.0.02026-10-22 · 0 installs · Ed25519-signed./install.sh oral-history-basics 1.0.0bundle (.zip)

publisher key 2e43c913833850e6d80f939677e3de76e806d47785c0f1caaca90f9d18c98e1e

Ratings

No ratings yet — be the first to rate it.