Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ jobs:
with:
node-version: 24.21.0
- run: npm run validate
- run: npm run check:composer-patterns
- run: node --test
- run: npm run validate:release
macos-install:
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,16 @@ Typst 0.15.1 hashes came from [official release asset metadata](https://api.gith
`docs/provenance/` preserves the signed Node list, public key and extracted
checksums. Neither origin settles signing, Gatekeeper or clean-Mac acceptance.

The composer's library guidance uses a checked-in copy of the 14 learning-patterns
READMEs and their MIT licence under `docs/provenance/learning-patterns/`.
`docs/provenance/learning-patterns.json` records the full source revision, source
URL and SHA-256 of each copied file. `npm run check:composer-patterns` verifies
those hashes and compares the use/avoid sections with `skills/composer/patterns.md`
without a network connection. CI runs this check. To update the source, copy the
READMEs and licence from a reviewed revision, update the provenance and hashes,
then run `npm run check:composer-patterns -- --write` and review the generated
diff. Keep Studio support and composition guidance outside the generated region.

Rubato's own scripts, skills and adapters are MIT-licensed (see `LICENSE`).
The tools it installs keep their own licences: Studio, Check, Trace, Print and
Import are under PolyForm Perimeter 1.0.1, with their third-party notices inside
Expand Down
22 changes: 22 additions & 0 deletions docs/provenance/learning-patterns.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"source": "https://github.com/Praxity/learning-patterns/tree/e9d4fb6989135a44d75f0765c61d3a596a5d4428",
"sourceRevision": "e9d4fb6989135a44d75f0765c61d3a596a5d4428",
"license": "MIT",
"files": {
"LICENSE": "d817c04f10efaffd1ab6dba0792a6567dce98f8ab41e86c64833a7b9cff7ecc5",
"patterns/conversation/README.md": "e7905b5f6428f051bd713925ab62d730c4439eb9f83156a7129081945109ed21",
"patterns/course-lookup/README.md": "fb51269d7d2cab7d04cc6f7405a14bcbaeac7bd48435c733c7ca243cbda0fdea",
"patterns/dont-know/README.md": "fb877c079d1dbda91245a793213b0bd34e53862c649d9458010cf7d3c3780b00",
"patterns/explain-back/README.md": "2de4bf358b88d386a07e6d9dd2ca79e11757e331e2eb6a6fa192b0c1a0b16f0f",
"patterns/first-answer/README.md": "f17127befa84657cee5b1a853aefbb5bd962c2c1a0063f14e7daec1e361f0fa9",
"patterns/highlight/README.md": "4f7d7615e079b92196b5cbb0c0f2c296683490d60db6e64fefaaa75a793ed91d",
"patterns/journal/README.md": "88942cf96636ced39926142462a364cf2c2292724e3c14caa01cf12a57cec4e8",
"patterns/live-feedback/README.md": "9dfbe57b30a9525e6ce10912952d51cc45d3896686822d8caa291a23940c9944",
"patterns/misconception/README.md": "26e45cdc9bbc70582571ebb3ab391db945848b9b9544a6e9f85a7aafebff2d17",
"patterns/retrieval-sheet/README.md": "30b017eb6121534538cdedf934d943b2e57cb4f058113367aadab03e8718aee8",
"patterns/review-prompts/README.md": "f53cbe5f287d64010f7a71209ca0172218c1cd009f2a85b34bd0370fcbe0de70",
"patterns/self-check/README.md": "b287cbc682d6aeb2d6788574cb9454e6ebd7f9f00247931a2d07d7a17f4a9614",
"patterns/test-out/README.md": "e5043437b7f91b2b56dc6e14f7d7a9ab8c9e9ef80b122420d8646aa88695cfb8",
"patterns/write-distractors/README.md": "91ccba1707d1a2b09ac3a78c55a57262411f6a8d6441c2d08276f039313488e2"
}
}
21 changes: 21 additions & 0 deletions docs/provenance/learning-patterns/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Ariel Harlap

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
108 changes: 108 additions & 0 deletions docs/provenance/learning-patterns/patterns/conversation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
title: Scenario talk-through
title_fr: Mise en pratique dans un scénario
summary: Practise two replies to an upset colleague and review what happened.
section: conversation
ai: yes
offline: yes
learners: not tried
---
# Scenario talk-through

You changed a work plan without asking Michel. Practise answering him in two rounds.

## Use it when

Use it to practise a difficult workplace conversation. You can acknowledge the impact, defend the change, attack, withdraw or ask for a pause. Michel responds to each choice. The review explains the effects of your two replies.

## Avoid it when

It gives no score.

## How it works

1. Read Michel’s opening line, write your reply and select "Say it", or open "Or choose a reply".
2. Read Michel’s response. Reply once more to finish the conversation.
3. Read the review of both replies. Select "Start over" to try another path.

Unclear or unrelated replies get guidance and open the five reply choices. Michel does not answer, and the round stays available. A pause shows a note that you return ten minutes later. Some endings include stage notes.

## Evidence

In a randomized study of 120 healthcare professionals, practising branching conversations with feedback improved three of four motivational interviewing measures more than further study of the material ([Reger et al., 2020](https://doi.org/10.1001/jamanetworkopen.2020.17348)). This supports conversation practice with consequences and feedback, but did not test this pattern. The content adapts the Gottman Institute's examples of repair attempts and the four horsemen from couple relationships to a workplace exchange ([Wilde, 2012](https://www.gottman.com/blog/manage-conflict-repair-and-de-escalate/); [Gottman Institute, 2013](https://www.gottman.com/blog/the-four-horsemen-the-antidotes/)). The decision model was tested only on agent-written answers. This two-round conversation and its effects on workplace conversations have not been tested with learners.

## Accessibility

Daily proxy caps show and announce the reason and midnight UTC reset once, keep focus in place and leave the fallback usable.

Meets the shared baseline in the root README.

- Each completed turn moves focus to Michel’s new line, including the final line. The reply controls hide or change only after focus arrives, so focus never falls to the page body. Focus announces the line once; the status region stays empty. Tab reaches the reply box, or "Start over" at the end.
- While a reply is sending, "Say it" keeps its label and focus, and pressing it again sends nothing. "Sending…" appears beside it. If the reply takes more than a second, the status region says "Sending…" once.
- If automatic checking fails while the reply box or "Say it" has focus, focus moves to the message "Automatic checking is unavailable. Choose a reply to continue." before the reply box hides. Focus reads the message, so the status region stays empty, and the next Tab reaches the first reply. If focus is elsewhere, the status region announces the message once.
- Unsure and off-script lines use the single status region without moving focus. Disclosures open immediately.
- Reply buttons have visible focus. Speech bubbles differ in position and speaker label, with borders in forced colours.
- Without the decision model, five reply buttons replace the reply box and support every path. Without JavaScript, nested disclosures show all 25 paths, stage notes and reviews.
- English and Québec French use identical fields. The French conversation uses vous.

## Content fields

All content is authored plain text, escaped before rendering.

| Field | Meaning |
| --- | --- |
| `setup` | Two sentences setting the meeting scene. |
| `person` | Michel’s `name`, `role` and avatar `initial`. |
| `subject`, `opening` | Composer subject and Michel’s opening line. |
| `branches` | The five fixed branch identities. |
| `branches[branch].line`, `.endings` | Michel’s first reply, then his final reply for each second move. |
| `branches[branch].move`, `.debrief` | Name of the learner’s response and one sentence about its effect. |
| `examples[node][branch]` | Five example replies for `opening` and each branch node, at most 1,200 characters each. |
| `stageNotes` | Optional italic ending notes keyed `first:second`. |
| `pauseNote` | Return to the conversation after a pause. |
| `unsure`, `offScript` | Helpful guidance that does not advance the conversation. |

The schema and validator reject unknown fields, missing branch IDs and blank text. Keep the English opening and first replies identical to the proxy’s `MICHEL_REPLIES`; tests check every line. French must convey the same context. To change the work-plan scenario, change and evaluate the proxy questions too.

## Logic

Authored text is capped at 120 characters for titles and labels, 400 for questions and prompts, 300 for options, and 1,500 for answers, explanations and passage text. Avatar `person.initial` is at most two characters; example replies stay capped at 1,200. The schema gives each field's limit; `validateContent` enforces it.


`logic.js` imports branch identities, the two-round limit, reply limit and decision model's confidence gate from the browser-safe `proxy/logic/03-contract.js`. That module owns the gate.

| Export | Returns |
| --- | --- |
| `validateContent(content)` | Nothing; throws an `Error` naming the bad field. |
| `start()` | `{ node: 'opening', round: 0, history: [], end: false }`. Also resets the conversation. |
| `feedback(answers, model?)` | A branch, `'unsure'` or `'off_script'`, from `{ branch: { choice, confidence } }`. Without a decision model, uses Jev's confidence gate, also used by the default Perplexity provider. Invalid answers throw. |
| `turn(content, state, branch, reply)` | `{ state, line, note }`. History stores `{ branch, reply }`; `end` becomes true after two moves. Unsure/off-script keep the state and return guidance as `note`. Further turns after the end throw. |
| `validateState(value)` | Clean `{ conversation, draft }`, or `null` if the history, node, round, end flag or draft is invalid. |
| `BRANCHES`, `REPLY_LIMIT` | The proxy-owned branch identities and maximum reply length. |

Pass `state: { read, write }` to save the draft and conversation. Invalid saved state is ignored. Editing during a check discards its result; restarting cancels requests. Repeated enhancement returns the same instance. `destroy()` removes listeners, cancels requests and restores the static script.

## Use it

Copy this folder, `lib/` and `proxy/logic/03-contract.js`, preserving relative paths. Include `lib/base.css`, then `pattern.css`. Give each instance a unique id prefix.

```js
import { render } from './patterns/conversation/render.js';
import { enhance } from './patterns/conversation/enhance.js';
import { strings } from './patterns/conversation/strings.js';
import { createAsk } from './lib/ask.js';

const markup = render(content, strings.en, { id: 'meeting', lang: 'en' });
const ask = createAsk({ endpoint: '/api/patterns', fetch: window.fetch.bind(window) });
enhance(document.querySelector('[data-lp-pattern="conversation"]'), { content, strings: strings.en, ask });
```

The shared client calls `ask('03-branch', { node, reply }, { challengeSlot, signal })`. Its `config()` supplies the decision model and bilingual data notice below the reply box. Turnstile appears inline after a clearance refusal. Missing `ask`, failed configuration, invalid answers or a failed request opens the reply choices. The demo uses a fixed classification and sends no text.

## Adapt it with your agent

> Adapt the example replies and reviews for [audience]. Keep the work-plan scenario, five branch IDs, two rounds, Michel’s opening and first lines, and all 25 endings. Write one plain review sentence per response and keep example replies under 1,200 characters. Write English and Québec French together, using vous. Keep authored dialogue and no scores.

## Licence

[MIT](../../LICENSE). Keep the licence notice with copied code.
Loading
Loading