You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Owner, 2026-09-21, while scoring rubric row 3c (the body double's first move, #30):
For reading text, could we also leverage an agent skill to parse the text and use a conversational style text to speech skill, short conversational output allowing the user to ask questions after each 'chunk' of output? Until we can support local 'live' voice that allows interruptions, this is the best option available.
The first move (#30) tells a low-energy learner to open the material and read for ten minutes, nothing more. This issue is the mode in which the companion does the reading with them, aloud, in pieces small enough to stop between.
What exists today (read from the code on main at fa1b2af3)
Voice per utterance.agents/shared/session-protocol.md "Voice Output": when the learner toggles @speak-start (/speak-start on Claude Code) the mentor runs ~/.local/bin/study-speak "<text>" for questions, answers and key principles — and explicitly not for long explanations. The web app posts text to POST /api/tts/speak (web/routes/tts.py), which proxies to the configured Kokoro-compatible server; window.ttsEngine.speak() (components.js) normalises and sentence-splits plain text before synthesis, and a header Stop button halts server audio mid-utterance (docs/voice-output.md). Both surfaces read the same tts: block in ~/.config/studyloop/config.yaml.
The text. MCP read_lesson(lesson_id) returns a lesson's raw markdown; the web Course Explorer panel renders the same content in place (GET /api/explorer/lesson/{id}/content → renderMarkdown).
The cadence. The co-study persona (agents/shared/personas/co-study.md) is "the student drives — stay quiet by default"; between pomodoro cycles it may check in briefly. The Socratic protocol is one short utterance per turn. Nothing today reads a lesson aloud, in any mode, on any harness.
The constraint. Owner rule on record: StudyLoop voice is one or two sentences per utterance, because the server synthesises the whole text before any audio plays and latency scales with length — a long passage is dead silence for its whole synthesis time.
What to build
A read-along mode of the co-study companion — an agent skill plus a protocol section, one behaviour on every supported harness:
Speak, then stop. Each rendering is spoken through the existing voice path (study-speak in terminal sessions, the web TTS in the browser) and the companion then waits: "Questions, or next?" The turn boundary is the interruption point — the learner asks, the companion answers Socratically within the persona's rules, then resumes with the next passage on "next".
The learner drives. The mode starts only when the learner asks for it (@read-along <lesson> / a Body Double control beside the Plan integration follow-on: the body double proposes one tiny, concrete first move on the deferred material #30 first move); it ends on "stop" or at the lesson's end with one closing line, and it never scores anything — a read-along is exposure, not evidence (the teach-back protocol's low-energy fallback already says the blank is not scored).
Every harness. The skill ships for the six supported harnesses (kiro-cli, Claude Code, Codex, OpenCode, pi, Grok Build) through the same agent-definition mechanism the other skills use; parity is checked by the existing agent-install contract tests, not assumed from kiro-cli alone.
Out of scope
Live, interruptible voice (barge-in). This issue is explicitly the bridge until that exists.
Reading arbitrary web pages or PDFs; the source is the indexed lesson content StudyLoop already serves.
A fake-agent e2e (the existing browser journey harness) proves the loop on one lesson: chunk spoken → pause → a learner question answered → "next" resumes → "stop" ends; every spoken chunk ≤ 2 sentences (measured, not asserted from the prompt).
The web path speaks each chunk through /api/tts/speak and the Stop button halts it; the terminal path runs study-speak once per chunk (pinned by the protocol contract test).
The skill exists for all six harnesses; test_install_agent_contracts.py / the agent manifest pin the parity; studyloop install agents prints it.
Docs: docs/voice-output.md gains a "Read-along" section; docs/web-ui-guide.md (Body Double) names the control; both pinned by a docs contract test.
A D-16 rubric row: row 3's world, the learner asks for read-along on the deferred material; the owner scores whether the first chunk is one they would listen to and ask about.
Definition of Done
Full unit suite green; just lint; just typecheck; e2e green in CI.
Council review of the RED and the arbitration before merge (one commit per accepted finding).
Spec delta (openspec/specs/socratic-methodology or voice-tts, whichever the design settles) and design in the same change; ships as a 0.5.N release.
Origin
Owner, 2026-09-21, while scoring rubric row 3c (the body double's first move, #30):
The first move (#30) tells a low-energy learner to open the material and read for ten minutes, nothing more. This issue is the mode in which the companion does the reading with them, aloud, in pieces small enough to stop between.
What exists today (read from the code on
mainatfa1b2af3)agents/shared/session-protocol.md"Voice Output": when the learner toggles@speak-start(/speak-starton Claude Code) the mentor runs~/.local/bin/study-speak "<text>"for questions, answers and key principles — and explicitly not for long explanations. The web app posts text toPOST /api/tts/speak(web/routes/tts.py), which proxies to the configured Kokoro-compatible server;window.ttsEngine.speak()(components.js) normalises and sentence-splits plain text before synthesis, and a header Stop button halts server audio mid-utterance (docs/voice-output.md). Both surfaces read the sametts:block in~/.config/studyloop/config.yaml.read_lesson(lesson_id)returns a lesson's raw markdown; the web Course Explorer panel renders the same content in place (GET /api/explorer/lesson/{id}/content→renderMarkdown).agents/shared/personas/co-study.md) is "the student drives — stay quiet by default"; between pomodoro cycles it may check in briefly. The Socratic protocol is one short utterance per turn. Nothing today reads a lesson aloud, in any mode, on any harness.What to build
A read-along mode of the co-study companion — an agent skill plus a protocol section, one behaviour on every supported harness:
read_lesson, or the lesson the Plan integration follow-on: the body double proposes one tiny, concrete first move on the deferred material #30 first move named), the companion splits it at headings/paragraph boundaries into passages and renders each passage as one or two conversational sentences in its own words — never the raw text read verbatim (that breaks the utterance rule and invites no question).study-speakin terminal sessions, the web TTS in the browser) and the companion then waits: "Questions, or next?" The turn boundary is the interruption point — the learner asks, the companion answers Socratically within the persona's rules, then resumes with the next passage on "next".@read-along <lesson>/ a Body Double control beside the Plan integration follow-on: the body double proposes one tiny, concrete first move on the deferred material #30 first move); it ends on "stop" or at the lesson's end with one closing line, and it never scores anything — a read-along is exposure, not evidence (the teach-back protocol's low-energy fallback already says the blank is not scored).Out of scope
Acceptance criteria
/api/tts/speakand the Stop button halts it; the terminal path runsstudy-speakonce per chunk (pinned by the protocol contract test).test_install_agent_contracts.py/ the agent manifest pin the parity;studyloop install agentsprints it.docs/voice-output.mdgains a "Read-along" section;docs/web-ui-guide.md(Body Double) names the control; both pinned by a docs contract test.Definition of Done
just lint;just typecheck; e2e green in CI.openspec/specs/socratic-methodologyorvoice-tts, whichever the design settles) and design in the same change; ships as a 0.5.N release.