From 85f03f1652ff756579e82e1a386345ef28ecd894 Mon Sep 17 00:00:00 2001 From: Ariel Harlap <3870784+aharlap@users.noreply.github.com> Date: Mon, 19 Oct 2026 21:02:02 -0400 Subject: [PATCH 1/2] Split pattern selection guidance into use and avoid sections Co-Authored-By: GPT-6.1 Sol --- patterns/conversation/README.md | 8 ++++++-- patterns/course-lookup/README.md | 4 +++- patterns/dont-know/README.md | 8 ++++++-- patterns/explain-back/README.md | 8 ++++++-- patterns/first-answer/README.md | 8 ++++++-- patterns/highlight/README.md | 8 ++++++-- patterns/journal/README.md | 8 ++++++-- patterns/live-feedback/README.md | 8 ++++++-- patterns/misconception/README.md | 8 ++++++-- patterns/retrieval-sheet/README.md | 4 +++- patterns/review-prompts/README.md | 8 ++++++-- patterns/self-check/README.md | 8 ++++++-- patterns/test-out/README.md | 4 +++- patterns/write-distractors/README.md | 8 ++++++-- scripts/pattern-meta.test.js | 11 +++++++++-- 15 files changed, 84 insertions(+), 27 deletions(-) diff --git a/patterns/conversation/README.md b/patterns/conversation/README.md index 45e9955..32e1fab 100644 --- a/patterns/conversation/README.md +++ b/patterns/conversation/README.md @@ -11,9 +11,13 @@ learners: not tried You changed a work plan without asking Michel. Practise answering him in two rounds. -## When to use it +## 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. It gives no score. +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 diff --git a/patterns/course-lookup/README.md b/patterns/course-lookup/README.md index cdafe9a..d853a2c 100644 --- a/patterns/course-lookup/README.md +++ b/patterns/course-lookup/README.md @@ -11,10 +11,12 @@ learners: not tried Ask about Assertive at work. The decision model picks an authored answer or a section of the course. It writes no answers. -## When to use it +## Use it when Use it across a course with a small, stable catalogue. The demo has eight FAQ entries and six course sections. Both shapes use the same renderer and enhancer, configured with `kind: 'faq' | 'sections'`. +## Avoid it when + For catalogues with more than about 30 entries, first narrow the candidates with embeddings. Check the chosen candidates against the learner's question before showing them. ## How it works diff --git a/patterns/dont-know/README.md b/patterns/dont-know/README.md index 1b858fb..dfbf2c8 100644 --- a/patterns/dont-know/README.md +++ b/patterns/dont-know/README.md @@ -11,9 +11,13 @@ learners: not tried Answer a quiz with an "I don't know" option. See your score, explanations and questions to review. -## When to use it +## Use it when -Use it for short practice quizzes where learners need a way to say they are unsure. Set points for right, wrong and unknown answers. Losing points for wrong answers may discourage guessing. Test the scoring with your learners before using it for assessment. +Use it for short practice quizzes where learners need a way to say they are unsure. Set points for right, wrong and unknown answers. Losing points for wrong answers may discourage guessing. + +## Avoid it when + +Test the scoring with your learners before using it for assessment. ## How it works diff --git a/patterns/explain-back/README.md b/patterns/explain-back/README.md index c4c0133..4f0bb72 100644 --- a/patterns/explain-back/README.md +++ b/patterns/explain-back/README.md @@ -11,9 +11,13 @@ learners: not tried Explain a lesson in your own words and check which key ideas you included. -## When to use it +## Use it when -Use it after a short reading. This example checks three ideas: stonewalling, announcing a pause and returning to the conversation. The feedback helps you revise your explanation. It gives no grade. +Use it after a short reading. This example checks three ideas: stonewalling, announcing a pause and returning to the conversation. The feedback helps you revise your explanation. + +## Avoid it when + +It gives no grade. ## How it works diff --git a/patterns/first-answer/README.md b/patterns/first-answer/README.md index 4748c34..a26bb22 100644 --- a/patterns/first-answer/README.md +++ b/patterns/first-answer/README.md @@ -11,9 +11,13 @@ learners: not tried Save an answer at the start of a course. Answer again at the end, then compare what changed. -## When to use it +## Use it when -Use it when learners can answer the same question at the start and end of a course. Keep the question and self-check criteria the same. Learners judge their own changes, so use another method to grade answers. +Use it when learners can answer the same question at the start and end of a course. Keep the question and self-check criteria the same. + +## Avoid it when + +Learners judge their own changes, so use another method to grade answers. ## How it works diff --git a/patterns/highlight/README.md b/patterns/highlight/README.md index 0206348..eed3510 100644 --- a/patterns/highlight/README.md +++ b/patterns/highlight/README.md @@ -11,9 +11,13 @@ learners: not tried Mark key ideas or text that answers a question. Then compare your marks with the author's choices in the passage. -## When to use it +## Use it when -Use it to find key ideas or evidence for a question. Keep passages short and split them into meaningful pieces. Learners select whole pieces, so use another pattern for selecting individual words. Searching visible text does not test recall. +Use it to find key ideas or evidence for a question. Keep passages short and split them into meaningful pieces. + +## Avoid it when + +Learners select whole pieces, so use another pattern for selecting individual words. Searching visible text does not test recall. ## How it works diff --git a/patterns/journal/README.md b/patterns/journal/README.md index 4324f4e..8dd5462 100644 --- a/patterns/journal/README.md +++ b/patterns/journal/README.md @@ -11,9 +11,13 @@ learners: not tried Reflect on practising assertiveness this week. Save your entry in your tab or ask for one optional question. -## When to use it +## Use it when -Use it for weekly course reflections. Each suggestion asks about the first missing detail: a situation, your response, a next step or when to try it. There is no score or checklist. +Use it for weekly course reflections. Each suggestion asks about the first missing detail: a situation, your response, a next step or when to try it. + +## Avoid it when + +There is no score or checklist. The distress check was tested only on agent-written answers. It shows an authored support message instead of a question. It does not diagnose, contact anyone or send alerts. Replace the message with your real support details. Test the decision model with your own examples before use with learners. diff --git a/patterns/live-feedback/README.md b/patterns/live-feedback/README.md index a9710d1..c35ea17 100644 --- a/patterns/live-feedback/README.md +++ b/patterns/live-feedback/README.md @@ -11,9 +11,13 @@ learners: not tried Write three actions to become more assertive at work. A checklist updates when you pause. The decision model selects authored feedback to help you revise. -## When to use it +## Use it when -Use it for short action plans, outline-like writing assignments, and generally to give learners immediate feedback on responses that can be classified. This example checks for three different actions a colleague could see or hear, a time or situation, and your own commitments. The feedback helps you revise. It gives no grade. +Use it for short action plans, outline-like writing assignments, and generally to give learners immediate feedback on responses that can be classified. This example checks for three different actions a colleague could see or hear, a time or situation, and your own commitments. The feedback helps you revise. + +## Avoid it when + +It gives no grade. ## How it works diff --git a/patterns/misconception/README.md b/patterns/misconception/README.md index 545c116..0a6d8d6 100644 --- a/patterns/misconception/README.md +++ b/patterns/misconception/README.md @@ -11,9 +11,13 @@ learners: not tried Answer a study question. Compare your reasoning with the feedback and model answer. -## When to use it +## Use it when -Use it when a short answer can reveal a mistaken belief. This example asks whether rereading notes prepares you for a test. The proxy checks four study misconceptions. Feedback helps you revise your reasoning. It gives no grade. +Use it when a short answer can reveal a mistaken belief. This example asks whether rereading notes prepares you for a test. The proxy checks four study misconceptions. Feedback helps you revise your reasoning. + +## Avoid it when + +It gives no grade. ## How it works diff --git a/patterns/retrieval-sheet/README.md b/patterns/retrieval-sheet/README.md index bf13bcf..1dddfbd 100644 --- a/patterns/retrieval-sheet/README.md +++ b/patterns/retrieval-sheet/README.md @@ -11,12 +11,14 @@ learners: not tried Print questions on the front and answers on the back. Choose a date to answer from memory and check your work. -## When to use it +## Use it when Use it for a short module with a few ideas or actions worth recalling. Keep questions focused and answers short. Learners can use the sheet without internet. Print it or save a PDF while connected. A SCORM package prints from its course files without fetching anything. +## Avoid it when + Choosing a date sends no reminder. Arrange one through your course host if needed. ## How it works diff --git a/patterns/review-prompts/README.md b/patterns/review-prompts/README.md index b720a21..627008b 100644 --- a/patterns/review-prompts/README.md +++ b/patterns/review-prompts/README.md @@ -11,9 +11,13 @@ learners: not tried Answer questions between reading sections, compare with the answers and see when to review. -## When to use it +## Use it when -Use it for short readings with facts or actions learners need to recall later. Give each section one focused question and a short answer. Ratings record what learners say they remembered. They do not verify recall or workplace performance. +Use it for short readings with facts or actions learners need to recall later. Give each section one focused question and a short answer. + +## Avoid it when + +Ratings record what learners say they remembered. They do not verify recall or workplace performance. ## How it works diff --git a/patterns/self-check/README.md b/patterns/self-check/README.md index 3dcdfc5..54d1a26 100644 --- a/patterns/self-check/README.md +++ b/patterns/self-check/README.md @@ -11,9 +11,13 @@ learners: not tried Write an answer, tick the parts it includes, then compare with a model. Hints help you add missing parts. -## When to use it +## Use it when -Use it when learners can check their answers against a short list of clear parts. It works offline and can help you compare self-checking with automated feedback. The pattern does not judge the learner's text. +Use it when learners can check their answers against a short list of clear parts. It works offline and can help you compare self-checking with automated feedback. + +## Avoid it when + +The pattern does not judge the learner's text. ## How it works diff --git a/patterns/test-out/README.md b/patterns/test-out/README.md index 44a7830..cd50072 100644 --- a/patterns/test-out/README.md +++ b/patterns/test-out/README.md @@ -11,10 +11,12 @@ learners: not tried Answer a short check to see which course sections you can skip and which to take. -## When to use it +## Use it when Use it for a small refresher where one or two questions can justify skipping a section. Advanced questions must test any prerequisite knowledge they credit. +## Avoid it when + Keep all sections required when the course needs proof that learners saw each one. The host course handles navigation and completion records. ## How it works diff --git a/patterns/write-distractors/README.md b/patterns/write-distractors/README.md index cc47268..927edd7 100644 --- a/patterns/write-distractors/README.md +++ b/patterns/write-distractors/README.md @@ -11,9 +11,13 @@ learners: not tried Answer from memory, then write wrong options and name the mistaken idea behind each. Compare your options with the author's. -## When to use it +## Use it when -Use it when learners know enough to answer from memory and explain common mistakes. Authors can review their wrong options for use in quizzes. A person must judge whether each option expresses the chosen misconception and would tempt a learner. Matching labels cannot do that. +Use it when learners know enough to answer from memory and explain common mistakes. Authors can review their wrong options for use in quizzes. + +## Avoid it when + +A person must judge whether each option expresses the chosen misconception and would tempt a learner. Matching labels cannot do that. ## How it works diff --git a/scripts/pattern-meta.test.js b/scripts/pattern-meta.test.js index 0822265..f4fc170 100644 --- a/scripts/pattern-meta.test.js +++ b/scripts/pattern-meta.test.js @@ -55,7 +55,7 @@ test('every pattern README has valid front matter', async () => { }); const README_SECTIONS = [ - 'When to use it', 'How it works', 'Evidence', 'Accessibility', + 'Use it when', 'Avoid it when', 'How it works', 'Evidence', 'Accessibility', 'Content fields', 'Logic', 'Use it', 'Adapt it with your agent', 'Licence' ]; @@ -67,9 +67,13 @@ function checkReadmeStructure(readme) { const prose = readme.replace(/^```[^\n]*\n[\s\S]*?^```[^\n]*$/gm, ''); const sections = [...prose.matchAll(/^## ([^\r\n]+)\r?$/gm)].map(match => match[1]); const expected = sections.includes('Write this in .prax') - ? README_SECTIONS.toSpliced(2, 0, 'Write this in .prax') + ? README_SECTIONS.toSpliced(3, 0, 'Write this in .prax') : README_SECTIONS; assert.deepEqual(sections, expected); + for (const heading of ['Use it when', 'Avoid it when']) { + const content = prose.split(`## ${heading}`)[1].split(/^## /m)[0].trim(); + assert.ok(content, `${heading} is empty`); + } const how = readme.split(/^## How it works\r?$/m)[1].split(/^## /m)[0]; assert.doesNotMatch(how, /`|\b[A-Za-z_$][\w.$]*\s*\(/, 'How it works contains code'); // READMEs are public. They never mention how they were written or where files sit on a machine. @@ -93,6 +97,9 @@ test('README structure guard catches missing, reordered and technical sections', for (const section of README_SECTIONS) { assert.throws(() => checkReadmeStructure(readme.replace(`## ${section}\n`, '')), section); } + for (const heading of ['Use it when', 'Avoid it when']) { + assert.throws(() => checkReadmeStructure(readme.replace(`## ${heading}\n\nPlain text.`, `## ${heading}\n`)), /is empty/); + } assert.throws(() => checkReadmeStructure(readme.replace('## Evidence', '## Temporary').replace('## Logic', '## Evidence').replace('## Temporary', '## Logic'))); assert.doesNotThrow(() => checkReadmeStructure(readme.replaceAll('\n', '\r\n'))); for (const code of ['`answer`', 'readingMinutes(content)', 'scheduleReview (date)']) { From 3ed3d0e2ccb373cc3646dd89a6dd33030fab58e6 Mon Sep 17 00:00:00 2001 From: Ariel Harlap <3870784+aharlap@users.noreply.github.com> Date: Mon, 19 Oct 2026 21:10:48 -0400 Subject: [PATCH 2/2] Move setup notes out of pattern selection guidance Co-Authored-By: GPT-6.1 Sol --- patterns/course-lookup/README.md | 6 +++++- patterns/dont-know/README.md | 6 +++++- patterns/journal/README.md | 2 ++ patterns/test-out/README.md | 6 +++++- scripts/pattern-meta.test.js | 26 +++++++++++++++++++------- 5 files changed, 36 insertions(+), 10 deletions(-) diff --git a/patterns/course-lookup/README.md b/patterns/course-lookup/README.md index d853a2c..5c5a38e 100644 --- a/patterns/course-lookup/README.md +++ b/patterns/course-lookup/README.md @@ -13,10 +13,14 @@ Ask about Assertive at work. The decision model picks an authored answer or a se ## Use it when -Use it across a course with a small, stable catalogue. The demo has eight FAQ entries and six course sections. Both shapes use the same renderer and enhancer, configured with `kind: 'faq' | 'sections'`. +Use it across a course with a small, stable catalogue. The demo has eight FAQ entries and six course sections. ## Avoid it when +## Setting it up + +Both shapes use the same renderer and enhancer, configured with `kind: 'faq' | 'sections'`. + For catalogues with more than about 30 entries, first narrow the candidates with embeddings. Check the chosen candidates against the learner's question before showing them. ## How it works diff --git a/patterns/dont-know/README.md b/patterns/dont-know/README.md index dfbf2c8..34f5826 100644 --- a/patterns/dont-know/README.md +++ b/patterns/dont-know/README.md @@ -13,12 +13,16 @@ Answer a quiz with an "I don't know" option. See your score, explanations and qu ## Use it when -Use it for short practice quizzes where learners need a way to say they are unsure. Set points for right, wrong and unknown answers. Losing points for wrong answers may discourage guessing. +Use it for short practice quizzes where learners need a way to say they are unsure. ## Avoid it when Test the scoring with your learners before using it for assessment. +## Setting it up + +Set points for right, wrong and unknown answers. Losing points for wrong answers may discourage guessing. + ## How it works 1. Read the scoring rule and choose an answer for each question. Choose "I don't know" when you are unsure. diff --git a/patterns/journal/README.md b/patterns/journal/README.md index 8dd5462..5b84b7b 100644 --- a/patterns/journal/README.md +++ b/patterns/journal/README.md @@ -19,6 +19,8 @@ Use it for weekly course reflections. Each suggestion asks about the first missi There is no score or checklist. +## Setting it up + The distress check was tested only on agent-written answers. It shows an authored support message instead of a question. It does not diagnose, contact anyone or send alerts. Replace the message with your real support details. Test the decision model with your own examples before use with learners. ## How it works diff --git a/patterns/test-out/README.md b/patterns/test-out/README.md index cd50072..2cc519d 100644 --- a/patterns/test-out/README.md +++ b/patterns/test-out/README.md @@ -17,7 +17,11 @@ Use it for a small refresher where one or two questions can justify skipping a s ## Avoid it when -Keep all sections required when the course needs proof that learners saw each one. The host course handles navigation and completion records. +Keep all sections required when the course needs proof that learners saw each one. + +## Setting it up + +The host course handles navigation and completion records. ## How it works diff --git a/scripts/pattern-meta.test.js b/scripts/pattern-meta.test.js index f4fc170..abd8fe2 100644 --- a/scripts/pattern-meta.test.js +++ b/scripts/pattern-meta.test.js @@ -59,19 +59,21 @@ const README_SECTIONS = [ 'Content fields', 'Logic', 'Use it', 'Adapt it with your agent', 'Licence' ]; -/** @param {string} readme */ -function checkReadmeStructure(readme) { - readMeta('pattern', readme); +/** @param {string} readme @param {string} [name] */ +function checkReadmeStructure(readme, name = 'pattern') { + readMeta(name, readme); assert.match(readme, /^---\r?\n[\s\S]*?\r?\n---\r?\n# [^\r\n]+\r?\n/); // Code examples may contain Markdown headings; they are not README sections. const prose = readme.replace(/^```[^\n]*\n[\s\S]*?^```[^\n]*$/gm, ''); const sections = [...prose.matchAll(/^## ([^\r\n]+)\r?$/gm)].map(match => match[1]); - const expected = sections.includes('Write this in .prax') - ? README_SECTIONS.toSpliced(3, 0, 'Write this in .prax') - : README_SECTIONS; + const expected = [...README_SECTIONS]; + if (sections.includes('Setting it up')) expected.splice(2, 0, 'Setting it up'); + if (sections.includes('Write this in .prax')) expected.splice(expected.indexOf('Evidence'), 0, 'Write this in .prax'); assert.deepEqual(sections, expected); for (const heading of ['Use it when', 'Avoid it when']) { const content = prose.split(`## ${heading}`)[1].split(/^## /m)[0].trim(); + // course-lookup has no avoid condition yet; keep its heading for the owner follow-up. + if (heading === 'Avoid it when' && name === 'course-lookup') continue; assert.ok(content, `${heading} is empty`); } const how = readme.split(/^## How it works\r?$/m)[1].split(/^## /m)[0]; @@ -91,6 +93,12 @@ test('README structure guard catches missing, reordered and technical sections', const withPrax = readme.replace('## Evidence', '## Write this in .prax\n\nPlain text.\n\n## Evidence'); assert.doesNotThrow(() => checkReadmeStructure(withPrax)); assert.doesNotThrow(() => checkReadmeStructure(withPrax.replaceAll('\n', '\r\n'))); + const withSetup = readme.replace('## How it works', '## Setting it up\n\nPlain text.\n\n## How it works'); + assert.doesNotThrow(() => checkReadmeStructure(withSetup)); + assert.doesNotThrow(() => checkReadmeStructure(withSetup.replaceAll('\n', '\r\n'))); + assert.doesNotThrow(() => checkReadmeStructure(withSetup.replace('## Evidence', '## Write this in .prax\n\nPlain text.\n\n## Evidence'))); + assert.throws(() => checkReadmeStructure(withSetup.replace('## How it works', '## Setting it up\n\nPlain text.\n\n## How it works'))); + assert.throws(() => checkReadmeStructure(readme.replace('## Evidence', '## Setting it up\n\nPlain text.\n\n## Evidence'))); assert.throws(() => checkReadmeStructure(readme.replace('## Logic', '## Write this in .prax\n\nPlain text.\n\n## Logic'))); assert.throws(() => checkReadmeStructure(withPrax.replace('## Evidence', '## Write this in .prax\n\nPlain text.\n\n## Evidence'))); assert.doesNotThrow(() => checkReadmeStructure(readme.replace('## Use it\n\nPlain text.', '## Use it\n\n```js\n## Example heading inside code\n```'))); @@ -100,6 +108,10 @@ test('README structure guard catches missing, reordered and technical sections', for (const heading of ['Use it when', 'Avoid it when']) { assert.throws(() => checkReadmeStructure(readme.replace(`## ${heading}\n\nPlain text.`, `## ${heading}\n`)), /is empty/); } + const emptyAvoid = readme.replace('## Avoid it when\n\nPlain text.', '## Avoid it when\n'); + assert.doesNotThrow(() => checkReadmeStructure(emptyAvoid, 'course-lookup')); + assert.throws(() => checkReadmeStructure(emptyAvoid, 'journal'), /is empty/); + assert.throws(() => checkReadmeStructure(readme.replace('## Use it when\n\nPlain text.', '## Use it when\n'), 'course-lookup'), /is empty/); assert.throws(() => checkReadmeStructure(readme.replace('## Evidence', '## Temporary').replace('## Logic', '## Evidence').replace('## Temporary', '## Logic'))); assert.doesNotThrow(() => checkReadmeStructure(readme.replaceAll('\n', '\r\n'))); for (const code of ['`answer`', 'readingMinutes(content)', 'scheduleReview (date)']) { @@ -117,7 +129,7 @@ test('every pattern README has the shared structure and plain learner steps', as for (const entry of await readdir(root, { withFileTypes: true })) { if (!entry.isDirectory()) continue; const readme = await readFile(new URL(`${entry.name}/README.md`, root), 'utf8'); - assert.doesNotThrow(() => checkReadmeStructure(readme), `${entry.name}/README.md`); + assert.doesNotThrow(() => checkReadmeStructure(readme, entry.name), `${entry.name}/README.md`); } });