@miadi/transcription
v0.1.0-alpha.0
Published
Read a composition's transcriptions by form and intent: label-grammar parsing, prose segmentation, and the semantic-correction advisory that warns and never rewrites.
Readme
@miadi/transcription
Reads a composition's transcriptions by form and intent, so a decomposer can route each one to the treatment it actually calls for.
This is the transcription aspect of the composition-recorder suite, and the
opportunistic partner of the transcription-decomposer. It carries the RISE
specs it implements in rispecs/.
It reads. It never writes. A composition belongs to the musician who recorded it. Nothing here repairs, normalizes, or rewrites a manifest, a transcription, or a take.
Install
npm i @miadi/transcription@alphaZero runtime dependencies — Node built-ins only. It installs on Termux.
The surface
import { readCompositionTexts, readTranscriptionEntry } from "@miadi/transcription"
const manifest = JSON.parse(await readFile("composition.json", "utf8"))
for (const reading of readCompositionTexts(manifest)) {
reading.format.format // monologue | request | plan | journal | dialogue | list | document | note | empty
reading.intent.genre // parsed from the hand-typed label's own grammar
reading.segments // addressable units, each with the move it makes
reading.corrections // the advisory — warns, never applies
reading.route // { approach, reason, suggestedStrategy }
}CLI
miadi-transcription read <composition-dir> # form, intent, segments, route per entry
miadi-transcription segments <composition-dir> # the segments themselves
miadi-transcription advise <composition-dir> # only the correction advisoryWhat it does, and why it does it that way
Segmentation is prose-driven, because the data is one line
In the real corpus a texts[].content is a single unbroken line — the
longest is 20,574 characters with no newline at all. There are no paragraphs to
split on, no timestamps, and no speaker turns. Segmentation therefore reads the
speech itself: sentence boundaries (guarding French abbreviations and decimals),
discourse markers that open a new movement (alors, donc, bref, so,
anyway), a size ceiling, and — most importantly — a shift in what the
speaker is doing.
That last seam is the one that matters. An ask followed by a stretch of deciding is otherwise one span whose dominant move is "decide", and the ask — the most decomposable thing in the whole transcription — stops being separately addressable.
Fidelity is a hard guarantee: segments.map(s => s.text).join("") reproduces
the source exactly, and every charStart/charEnd indexes the original string.
Verified across all 1064 segments the corpus produces.
The label grammar is mined, not invented
texts[].label is free text, and across the corpus it carries a consistent
unwritten grammar that lived only in its author's head:
RequestToJerryFromWilliam → genre=request to=Jerry from=William
InitByWilliamReadyForJerry → genre=handoff by=William readyFor=Jerry
Rel2ep099ep075ep103 → relatesTo=[ep099, ep075, ep103]
MultiHasDesiredProcesses2filmInEp103 → multi=true relatesTo=[ep103]
Cycle6to7…Question2Jerry-da8002… → cycles=[6-7] to=JerryEvery genre keyword and token pattern was derived from the 86 labels actually present in the corpus. ~30% of those labels are empty, so the contract is absolute: absence means infer, never invalid.
The advisory warns and never rewrites
Per transcription.spec.md, recurring mishearings are resolved by warning.
There is deliberately no applyCorrections export, and there never should be.
Every table entry was verified against the corpus before being encoded, and two
plausible-looking candidates were rejected on inspection: Ermes (11 hits —
all the French "en termes de") and Media (Plex, spelled correctly). A table
that flags correct speech is worse than no table.
| Heard | Intended | Source |
|---|---|---|
| TallyScale · TaylorSkills · Tailscal | Tailscale | corpus |
| Niro | Nyro | corpus |
| Thermux | Termux | corpus |
| Kauaia | coaia | corpus |
| Orion | Aureon | corpus (low confidence — read the passage) |
| medicine roll | medicine wheel | spec |
Additive and opportunistic
texts[].format, texts[].corrections, and texts[].intent are optional fields
a composition may or may not carry. A present field is authoritative and is
never second-guessed; an absent one is inferred. No manifest version bump,
and a reader that ignores these fields is unaffected.
Routing
| Form | Approach | miaco --strategy |
|---|---|---|
| request · handoff · plan · list · document · note | direct | standard |
| monologue · journal | layered | iterative-refinement |
| dialogue · two named voices | multi-voice | adversarial-consensus |
suggestedStrategy is a hint, not a coupling — this package knows nothing
about miaco, and a consumer is free to map approach itself. A directed act
(RequestToJerryFromWilliam) names two people because it has a sender and a
receiver; that is direction, not turn-taking, so it routes direct.
Transcribing
transcribeTake() is the logic extracted from the recorder monolith's
transcribeAudio — same hosted service, same model, two renderings both asked
of the audio (never one translated from the other). The credential gate
declines with a reason rather than throwing, and the take is left exactly as it
was.
Unlike the monolith, it does not write the sidecar: the record is returned and the caller decides. This package never writes into a musician's library.
Tests
npm test