Repository navigation
Conversation
The Magic Compose prompt now describes the questions reply and when to use it: only when the prompt doesn't say what people sign up for, listing only the topics it leaves out, with two to four options in the prompt's language and never a date or a count, since the app asks for those itself. A message that carries the organizer's answers is never answered with questions. The drafter's never-invent rule splits in two. No "what" asks; a prompt that says what but not when or how many still drafts "TBD:" rows, which the builder's placeholder checks rely on. Example C, the vague soccer prompt, becomes a questions reply, and a new Example D keeps the placeholder pattern for "Snack duty for the soccer team, two families per game". The prompt also says capacity may be null, which is where the follow-up's "no limit" lands. RULES_IN_BOTH and the assistant's rule are untouched, so the MCP server instructions don't change. The golden file is regenerated. A new test parses every worked example with the server's schema, and others hold the prompt to the follow-up message's label and its "no limit". Part of #570. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UW9ZpEu4MWkeqTv2Qe14ks
The eval script treated a questions reply as a failed call, so nothing measured whether the prompt asks when it should. The harness gains a questions arm: a case with questions.* checks expects one (a draft fails as expected_questions_but_drafted), and questions anywhere else fail as unexpected_questions, as a stray refusal does. The checks cover the topics asked (include, exclude, equal), the number of options, options holding a date or a number, and whole-word matches on the options, which the French case uses to check they are in French. A case with `answers` runs both calls the page makes: the prompt, which must ask, then the prompt with the answers through FollowUpSchema and buildFollowUpMessages, whose draft the existing checks score. Questions there fail as asked_again. It is a new key because followUps already means organizer turns in the MCP runner. ev_008 now expects questions instead of 1-6 placeholder slots, and ten made-up cases cover name-only prompts, a date with no "what", a French prompt, near misses that must still draft (with "TBD:" rows where the slots need dates), and drafts from answers and from Draft with placeholders. pnpm eval:mcp reads the same file. An assistant that asks the organizer is right where Magic Compose would ask, so there a reply passes as asked_before_creating; "assistant_may_ask" marks the two placeholder cases where an assistant may ask for the dates instead; cases with answers are skipped. Every existing case scores as before. Part of #570. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UW9ZpEu4MWkeqTv2Qe14ks
Both calls of a questions round reach the AI, so both count: a description that gets questions now uses two drafts. Two more an hour make up for a couple of those. The route's comment no longer names the number, so it can't go stale again. Part of #570. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UW9ZpEu4MWkeqTv2Qe14ks
When the description doesn't say what people sign up for, the organizer now answers a few questions and the answers are sent to the AI provider with it. The privacy page's Third parties paragraph says so; it still names nothing else about the organizer and nothing about participants. The Last updated date is already today's. The CHANGELOG gains the line for the questions round being on: what asks and what still drafts, the quota going to 12 an hour, and the evals, with ev_008 now expecting questions. Part of #570. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UW9ZpEu4MWkeqTv2Qe14ks
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UW9ZpEu4MWkeqTv2Qe14ks
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UW9ZpEu4MWkeqTv2Qe14ks
…al from copying an example
Rule 4 told the drafter to ask whenever a prompt doesn't say what people
sign up for, with the exception only in the QUESTIONS section. Draft with
placeholders sends exactly that ("What people sign up for: not given"),
so it was the follow-up most likely to be asked again. The rule now says
"and carries no answers to your questions" itself.
Example D's prompt was word for word ev_033's, so that case measured
copying the example rather than the rule. Example D is now school play
ushers, two parents per performance; ev_033 keeps the design's snack duty
prompt. Golden file regenerated; the diff is these two changes.
Part of #570.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UW9ZpEu4MWkeqTv2Qe14ks
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UW9ZpEu4MWkeqTv2Qe14ks
This was referenced Oct 24, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UW9ZpEu4MWkeqTv2Qe14ks
The review of the eval harness found it disagreeing with the route and the page in a few places, so its scores could mislead. A reply to the answers that asks again with only part of a question (just "when", say) was scored as a broken draft. It is now asked_again, read with asksQuestions as the route reads it. The second call now sends "when" and "how many" only when the first call asked about them, as the page does; when the first call drafted instead, the answers still go back as written. A case's answers are checked with FollowUpSchema before any paid call, and a bad one is reported as a broken case rather than an LLM failure. When the second call fails, its error says "second call:" and the first call's checks are still printed. "questions.must_ask": false now expects a draft instead of counting as a questions case. In eval:mcp a reply passes an ask case only when it asks something (holds a "?"), so a refusal or an empty reply fails. French number words join the date-or-number check for the French case. asksFirst loses a branch nothing could reach. The harness gets its own unit tests, so vitest now also runs scripts/**/*.test.ts. The changed files are run through prettier. Part of #570. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UW9ZpEu4MWkeqTv2Qe14ks
#526 added its own ev_027 (the classroom starter), so this branch's new cases are renumbered ev_028 to ev_037; the README follows. The prompt and its golden file merge cleanly: #526's CAPACITY section and this branch's QUESTIONS section both render, and the golden-file test passes. The quota line keeps 12 beside #525's link-events limit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UW9ZpEu4MWkeqTv2Qe14ks
This was referenced Oct 24, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UW9ZpEu4MWkeqTv2Qe14ks
richshaw
added this pull request to stack #618
October 25, 2026 17:21
Through the server, telemetry and screen branches. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UW9ZpEu4MWkeqTv2Qe14ks
…he 5-prompt branch Through the server, telemetry and screen branches. rate-limit.ts keeps this branch's 12 drafts an hour and main's reworded link-beacon comment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UW9ZpEu4MWkeqTv2Qe14ks
Through the server, telemetry and screen branches. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UW9ZpEu4MWkeqTv2Qe14ks
Through the server, telemetry and screen branches. No conflicts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UW9ZpEu4MWkeqTv2Qe14ks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #570, the last of five stacked PRs. It's based on #576 (the questions screen). This is the PR that turns the questions on.
The problem
A Magic Compose description that's only an event's name, like "Bake sale", gives the model nothing to build slots from. It either makes three "TBD" rows or invents jobs and counts, and the organizer still uses one of the hour's drafts.
The fix
The prompt
Rule 4 (the drafter's never-invent text,
NEVER_INVENT_MIDDLE.drafterinsignup-rules.ts) now splits two cases:RULES_IN_BOTHand the AI connector's instructions are unchanged, and their tests prove it.A QUESTIONS section after the output schema gives the reply shape and its rules:
Capacity may be
nullfor no limit, which the follow-up message's "no limit" relies on.The worked examples:
{"questions":{"topics":["what","when","how_many"],"whatOptions":["Bring snacks","Drive to away games","Help at practice"]}}.TBD: performance 1–3with 2 spots each. Find fixable problems in a draft and offer one-tap fixes #503 relies on those "TBD:" rows.The golden file is regenerated; its diff is only these changes. With #526 now on
main, the prompt carries both #526's CAPACITY section and this QUESTIONS section, and the golden-file test passes. A test parses every worked example with the server's schema.Evals
The harness (
scripts/lib/eval-harness.ts,scripts/eval-magic-compose.ts):questionsresult arm.unexpected_questions;expected_questions_but_drafted;asked_again: questions in reply to the answers, in any shape, read with the route's ownasksQuestions.questions.must_ask(true or false),topics_must_include,topics_must_not_include,topics_must_equal,options_count_range,options_must_not_contain_date_or_number(English and French number words, months and weekdays),options_must_mention_anyandoptions_must_not_mention_any.answers(aFollowUp) is checked withFollowUpSchemabefore any model call. The first call must ask. Then the answers go throughbuildFollowUpMessages, as in the route, and the draft is scored.whenonly if the first call asked "when",howManyonly if it asked "how_many".answersis a new key becausefollowUpsalready means the MCP runner's organizer turns.scripts/lib/eval-harness.test.tstests the harness's own logic. For it to run,vitest.config.tsnow includesscripts/**/*.test.ts.pnpm eval:mcploads the same file:asked_before_creating, but only with a non-empty reply containing a "?". A refusal or an empty reply fails, and a create fails.answerscases are skipped.Cases. #526 added
ev_027(the classroom starter), so this PR's new cases areev_028–ev_037, andev_008flips from "drafts 1–6 slots" to "asks".ev_028ev_029ev_030ev_031ev_032ev_033ev_034ev_035ev_036nullfor no limitev_037Quota
magicComposePerOrganizergoes from 10 to 12 an hour. A thin description now takes two AI calls: the first, and the one with the answers. The free retry doesn't count. No docs or pages named the old number.Privacy and changelog
The privacy page already says the answers go to the AI provider (#573). CHANGELOG has a line under Added.
Your two open questions
I took the issue's defaults:
The evals haven't run against a real model
This session has no LLM endpoint. Against a local fake OpenAI-compatible endpoint:
--tag=questions);ev_001–ev_026score line for line as before.Those scores say nothing about the prompt itself. Before merging, please run, on this branch and on
main, and compare:Watch:
ev_037(Draft with placeholders): the prompt's rule 4 now exempts a message that carries answers, so it shouldn't ask again;ev_030(it mustn't ask for the date);ev_031(French options).Reviews
/code-review), fixed in 7b78492. It found eight harness issues:must_ask: falsemeant the opposite;eval-harness.ts,eval-mcp.tsand the README, files this PR already rewrites.Tophat
On this branch alone, against the fake endpoint:
Tests
pnpm lint && pnpm typecheck && pnpm knip && pnpm test(1488) andpnpm test:db(569) pass.🤖 Generated with Claude Code
https://claude.ai/code/session_01UW9ZpEu4MWkeqTv2Qe14ks