practice: the learner's creation note — optional free-form input carried to partitioner + generators (owner, 2026-09-29)

- dialog: optional 'Anything else?' textarea (typing-only, 2000-char mirror)
- API: body gains note? — trimmed, whitespace-only omitted, hard 400 over 2000
- pipeline: note persisted on the set and threaded to both agent stages
- agents: THE LEARNER'S NOTE prompt block (present only when set) + the
  weighed-never-owed stance pinned in both doctrines
- fix en route: doubled THE PARAMETERS heading in both prompts since slice 3
  (renderParams owns the heading; the literal blocks removed)
This commit is contained in:
amosblomqvist
2026-09-29 22:16:28 +03:00
parent cf0ec4a2f0
commit 06032769d2
15 changed files with 593 additions and 266 deletions
+13
View File
@@ -87,6 +87,8 @@ describe("PracticeDialogBody — creation (cluster picker)", () => {
const base = {
params: { ...DEFAULT_PRACTICE_PARAMS },
onParam: () => {},
note: "",
onNote: () => {},
clusters: clusters(),
selectedKey: null,
onSelect: () => {},
@@ -126,6 +128,17 @@ describe("PracticeDialogBody — creation (cluster picker)", () => {
assert.match(moved, /param-presentation-application[^]*border-primary/, "application segment active");
});
it("the learner's note: optional textarea under the params, carries text, capped client-side", () => {
const html = renderToStaticMarkup(<PracticeDialogBody {...base} note="lean toward pricing applications" />);
assert.ok(html.includes('data-testid="practice-note"'));
assert.ok(html.includes("Anything else? (optional)"), "the label");
assert.ok(html.includes("lean toward pricing applications"), "controlled value renders");
assert.match(html, /maxlength="2000"/i, "client-side cap mirrors the API law");
// Empty default: present but empty — optional in every sense.
const bare = renderToStaticMarkup(<PracticeDialogBody {...base} />);
assert.match(bare, /data-testid="practice-note"[^>]*><\/textarea>/, "no value when unset");
});
it("cluster picker: label + proposition-count rows, notes kind marked, Create gated until picked", () => {
const html = renderToStaticMarkup(<PracticeDialogBody {...base} />);
assert.ok(html.includes('data-testid="practice-dialog-clusters"'));