@a-t-h-i/bot-lobby 0.6.15 → 0.6.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -302,7 +302,7 @@ and your comments on it.
302
302
 
303
303
  ![The Plan tab](https://raw.githubusercontent.com/a-t-h-i/bot-lobby/main/docs/lobby-plan.png)
304
304
 
305
- The panel's questions, with recommended options, on the left; the draft plan
305
+ The panel's questions, with their options, on the left; the draft plan
306
306
  on the right. See [Planning](#planning).
307
307
 
308
308
  ### Quick fix
@@ -497,7 +497,7 @@ has them as well.
497
497
  ### The questionnaire
498
498
 
499
499
  `ask_user_question` puts up to four questions to you in one pop-up in the
500
- lobby page, each with two to four options (the recommended one first).
500
+ lobby page, each with two to four options. Agents do not recommend an answer, so you think it through; only a quite obvious one is marked `(Recommended)`.
501
501
  Questions, option descriptions and **previews** are Markdown: an option's
502
502
  preview (a layout sketch, a component mockup, a code snippet, a config) shows
503
503
  beside the list while that option is focused, under it in a narrow window, so
@@ -568,7 +568,7 @@ else TypeSafe.
568
568
  | Decision | Effect |
569
569
  | --- | --- |
570
570
  | Planning seats | Each round, only the seats the idea or your latest answers touch sit; `1`–`4` pins a seat |
571
- | Obvious answers | Answers a question itself when the conversation already makes the recommended option clearly right (≥ 0.9); listed under Assumptions |
571
+ | Obvious answers | Answers a question itself when the conversation already makes an option marked `(Recommended)` clearly right (≥ 0.9); listed under Assumptions |
572
572
  | File hints | Agents start with a short list of the files they most likely need, and get a `find_relevant_files` tool |
573
573
  | Relevant knowledge | When an agent's knowledge, standards or decisions file is too long for its prompt (over 4,000 characters), Jev keeps the sections that bear on the step, and the prompt says how many it left out and where the whole file is, so the agent can read the rest. A file that fits goes in whole, untouched; standards are never left empty |
574
574
  | Quick fix or task | Whether one engineer can do a new request alone decides whether it goes to the [quick-fix agent](#quick-fix-or-the-team) (the oracle confirms) |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a-t-h-i/bot-lobby",
3
- "version": "0.6.15",
3
+ "version": "0.6.16",
4
4
  "description": "Structured multi-agent software engineering orchestrator for Pi",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
package/prompts/master.md CHANGED
@@ -71,14 +71,17 @@ otherwise. It is a hint, never a rule.
71
71
 
72
72
  When the user leaves your questions unanswered (they put them away, or
73
73
  `ask_user_question` says so), the decision is still theirs: never assume the
74
- answers, never fall back on the recommended options, and never carry on with
74
+ answers, never fall back on a marked option, and never carry on with
75
75
  work that depends on them. Say in one short line that the questions are
76
76
  waiting, end your turn, and ask again when they next write.
77
77
 
78
- When you `clarify` with options, put your recommended option first and mark
79
- it `(Recommended)`. When the request already makes it clearly right, the
80
- classifier answers for you: the reply says so, the decision is recorded, and
81
- you mention it in the proposal so the user can amend it.
78
+ When you `clarify`, do not recommend an answer: the point is that the user
79
+ thinks the decision through. List the options neutrally (no `(Recommended)`
80
+ marker, none first because you prefer it, no hint of your own pick) and let
81
+ the user decide. Mark an option `(Recommended)` only when the answer is quite
82
+ obvious from the request or the repository; then the classifier may answer for
83
+ you: the reply says so, the decision is recorded, and you mention it in the
84
+ proposal so the user can amend it.
82
85
 
83
86
  The designer worker may ask the user itself (outside auto mode): visual
84
87
  choices it cannot settle alone, shown with Markdown wireframes or rendered
package/prompts/panel.md CHANGED
@@ -25,9 +25,12 @@ questions and the user's answers, and the oracle's current draft plan.
25
25
  - Ask at most two questions, the most important first. They go to the
26
26
  oracle, who picks at most four for the user each round across the whole
27
27
  panel and decides the rest with your recommendation, so make each one
28
- short, plain and specific, and give it two to four options, your
29
- recommendation first with `(Recommended)` after its label. The user can
30
- always type their own answer instead, so do not add an "Other" option.
28
+ short, plain and specific, and give it two to four options in a neutral
29
+ order. Do not recommend one: the user should think the decision through.
30
+ Only when the answer is quite obvious from the conversation or the
31
+ repository, put that option first with `(Recommended)` after its label. The
32
+ user can always type their own answer instead, so do not add an "Other"
33
+ option.
31
34
  - Read the draft's Assumptions: if one the oracle made for your seat is
32
35
  wrong, say so under Notes and ask about it again.
33
36
  - If an answer from the user is vague or conflicts with what you see in the
@@ -44,11 +47,12 @@ OPEN or READY
44
47
 
45
48
  ## Questions
46
49
  1. The question, ending with a question mark?
47
- - Short label (Recommended) — what choosing it means
50
+ - Short label — what choosing it means
48
51
  - Another label — what choosing it means
49
52
 
50
- (Two to four options per question, labels of one to five words. Omit
51
- Questions when READY.)
53
+ (Two to four options per question, labels of one to five words, no
54
+ recommendation unless the answer is quite obvious, and then only that option
55
+ carries `(Recommended)`. Omit Questions when READY.)
52
56
 
53
57
  ## Notes
54
58
  - …
@@ -6,8 +6,8 @@ without guessing. The panel's domain members — DEV, DESIGN, QA and RESEARCH
6
6
  bring you their questions each round, and you decide which ones reach the
7
7
  user: you own the plan and the questions. You are thorough but you spare the
8
8
  user: every decision that changes the implementation gets made, either by the
9
- user or by you with the recommended option, written down as an assumption the
10
- user can overrule. You never
9
+ user or, when the answer is quite obvious, by you, written down as an
10
+ assumption the user can overrule. You never
11
11
  write code and never change files; you may read the repository to ask
12
12
  informed questions and to ground the plan in what exists.
13
13
 
@@ -30,23 +30,26 @@ below.
30
30
  one of the questions.
31
31
  - Keep each question short and plain: one line the user can answer at a
32
32
  glance. Give it two to four options — labels of one to five words and a
33
- short clause on what each means — your recommendation first with
34
- `(Recommended)` after its label. The user answers all of them together in
35
- one dialog and can type their own answer, so never add an "Other" option.
33
+ short clause on what each means — in a neutral order. Do not recommend an
34
+ option: the user should think each decision through. Only when the answer is
35
+ quite obvious from the conversation or the repository, put that option first
36
+ with `(Recommended)` after its label. The user answers all of them together
37
+ in one dialog and can type their own answer, so never add an "Other" option.
36
38
  - The conversation may carry an **Already settled with the user** list:
37
39
  questions the user answered (or left for you to decide). They are closed in
38
40
  any wording, so never ask one again, not even rephrased; fold the answer
39
41
  into the plan. The engine drops a repeat before the user sees it, so asking
40
42
  again only wastes a round. Ask about something new, or ask nothing.
41
43
  - Decide every question you do not ask, and any the user leaves unanswered,
42
- with its recommended option, and list those decisions under
44
+ with the marked option where there is one and otherwise your best call, and
45
+ list those decisions under
43
46
  `### Assumptions` in the plan, one line each, so the user can see and
44
47
  overrule them.
45
48
  - Challenge answers that are vague, contradictory or risky, and ask again.
46
49
  Do not accept "whatever you think" for a decision with real trade-offs:
47
50
  propose one and ask the user to confirm it.
48
51
  - The conversation may show questions **decided by the classifier**: a
49
- fast model answered them with their recommended option because the
52
+ fast model answered them with their marked option because the
50
53
  conversation already made it clearly right. Treat them as answered, list
51
54
  each under `### Assumptions` (the user can overrule it), and do not ask
52
55
  them again.
@@ -62,7 +65,7 @@ GRILLING.
62
65
  Planning may be limited to a number of rounds; your task says which round
63
66
  this is. Ask the questions that change the most early. In the final round,
64
67
  and in any round after it, no member runs and nothing more is asked: fold the
65
- answers into the plan, decide every open point with its recommended option,
68
+ answers into the plan, decide every open point (the marked option where there is one, otherwise your best call),
66
69
  list each under `### Assumptions`, omit the Questions section and set the
67
70
  status READY.
68
71
 
@@ -76,12 +79,12 @@ Three to six words naming the task.
76
79
 
77
80
  ## Questions
78
81
  1. [DEV] The most important open question?
79
- - Short label (Recommended) — what choosing it means
82
+ - Short label — what choosing it means
80
83
  - Another label — what choosing it means
81
84
  2. …
82
85
 
83
86
  (At most four questions, each tagged with its seat; two to four options per
84
- question, labels of one to five words. Omit the Questions section when READY
87
+ question, labels of one to five words, `(Recommended)` only on an obvious one. Omit the Questions section when READY
85
88
  or when you decided everything yourself.)
86
89
 
87
90
  ## Plan
package/src/ask/tool.ts CHANGED
@@ -26,7 +26,7 @@ const OptionSchema = Type.Object({
26
26
  const QuestionSchema = Type.Object({
27
27
  question: Type.String({ description: "The whole question, clear and specific, ending with a question mark. Markdown." }),
28
28
  header: Type.String({ maxLength: MAX_HEADER, description: `A short chip naming the question (at most ${MAX_HEADER} characters), e.g. "Auth" or "Layout".` }),
29
- options: Type.Array(OptionSchema, { minItems: MIN_OPTIONS, maxItems: MAX_OPTIONS, description: `${MIN_OPTIONS}-${MAX_OPTIONS} distinct options. Put the one you recommend first and end its label with "(Recommended)". The user can always answer in their own words instead.` }),
29
+ options: Type.Array(OptionSchema, { minItems: MIN_OPTIONS, maxItems: MAX_OPTIONS, description: `${MIN_OPTIONS}-${MAX_OPTIONS} distinct options in a neutral order. Do not recommend one: the user should think the decision through. Only when the answer is quite obvious, put that option first and end its label with "(Recommended)". The user can always answer in their own words instead.` }),
30
30
  multiSelect: Type.Optional(Type.Boolean({ description: "True when several answers can apply together." })),
31
31
  });
32
32
 
@@ -36,7 +36,7 @@ export const AskParams = Type.Object({
36
36
 
37
37
  const DESCRIPTION = [
38
38
  "Ask the user one to four questions with options to pick from, when the answer would change what you do and you would otherwise guess.",
39
- "Each question has 2-4 options (the one you recommend first, its label ending in \"(Recommended)\"); the user can pick one (or several with multiSelect), or answer in their own words.",
39
+ "Each question has 2-4 options in a neutral order, with no recommendation (mark one \"(Recommended)\", first, only when the answer is quite obvious); the user can pick one (or several with multiSelect), or answer in their own words.",
40
40
  "Questions, descriptions and previews are Markdown. Give options a `preview` when the user needs to see them to choose: a UI mockup, a layout sketch, a code snippet, a config; the focused option's preview shows beside the list. An option can also carry an `image` file (a screenshot, a rendered mockup).",
41
41
  "Do not use it for yes/no confirmations of what you were already told to do, or for questions the conversation already answers.",
42
42
  ].join(" ");
@@ -208,13 +208,14 @@ export function triageLine(triage: TaskTriage): string {
208
208
 
209
209
  /**
210
210
  * A clarify question the classifier can answer: its pick must be the
211
- * recommended option (marked `(Recommended)`, else the first), confident and
212
- * clearly ahead; otherwise the question goes to the user as before.
211
+ * recommended option (marked `(Recommended)`; an unmarked question always goes
212
+ * to the user), confident and clearly ahead.
213
213
  */
214
214
  export async function answerClarify(classifier: Classifier, question: string, options: readonly string[], context: { request: string; notes: string; proposal?: string }, signal?: AbortSignal): Promise<AutoAnswer | undefined> {
215
215
  if (options.length < 2 || !classifier.enabled("answers")) return undefined;
216
216
  const labels = options.map((option) => option.replace(/\s*\(recommended\)\s*/i, " ").trim());
217
217
  const marked = options.findIndex((option) => /\(recommended\)/i.test(option));
218
- const decided = await autoAnswer(classifier, [{ index: 0, from: "MASTER", text: question, options: labels.map((label) => ({ label, description: "" })), recommended: labels[marked >= 0 ? marked : 0]! }], { request: context.request, conversation: context.notes, ...(context.proposal ? { draft: context.proposal } : {}) }, signal);
218
+ if (marked < 0) return undefined;
219
+ const decided = await autoAnswer(classifier, [{ index: 0, from: "MASTER", text: question, options: labels.map((label) => ({ label, description: "" })), recommended: labels[marked]! }], { request: context.request, conversation: context.notes, ...(context.proposal ? { draft: context.proposal } : {}) }, signal);
219
220
  return decided?.[0];
220
221
  }
package/src/lobby/ask.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * The oracle puts the planning panel's questions to the user through the
3
- * questionnaire (`../ask`): a card per question with each seat's options, the
4
- * recommended one first, and a field for an answer in the user's own words.
3
+ * questionnaire (`../ask`): a card per question with each seat's options (the
4
+ * recommended one first when the answer is obvious), and a field for an answer in the user's own words.
5
5
  * The panel's questions become questionnaires of at most four, and the
6
6
  * answers become the user's turn for the next round.
7
7
  */
@@ -173,10 +173,10 @@ export function roundMode(round: number, limit: number): RoundMode {
173
173
  /** What the oracle is told to do at the end of its task, by round mode. */
174
174
  export function oracleClosing(mode: RoundMode, round: number, limit: number): string {
175
175
  if (mode === "final") {
176
- return `Final round (${round} of ${limit}): no seat runs this round and nothing more is asked. Fold the user's answers into the plan, decide every point still open with its recommended option and list each under ### Assumptions, and set Status READY. Omit the Questions section. Reply in the required output format.`;
176
+ return `Final round (${round} of ${limit}): no seat runs this round and nothing more is asked. Fold the user's answers into the plan, decide every point still open (with its marked option where there is one, otherwise your best call) and list each under ### Assumptions, and set Status READY. Omit the Questions section. Reply in the required output format.`;
177
177
  }
178
178
  if (mode === "revise") {
179
- return `The planning round limit (${limit}) is reached: revise the plan for the user's latest message and comments. Ask nothing; decide anything open with its recommended option under ### Assumptions, and keep Status READY. Omit the Questions section. Reply in the required output format.`;
179
+ return `The planning round limit (${limit}) is reached: revise the plan for the user's latest message and comments. Ask nothing; decide anything open (with its marked option where there is one, otherwise your best call) under ### Assumptions, and keep Status READY. Omit the Questions section. Reply in the required output format.`;
180
180
  }
181
181
  const bound = limit > 0 ? `Round ${round} of ${limit}; in round ${limit} you settle whatever is still open alone, so ask the decisive questions now. ` : "";
182
182
  return `${bound}Continue: fold the panel's notes and the user's answers into the plan, ask what no seat owns, or declare the plan READY. Reply in the required output format.`;
@@ -225,9 +225,9 @@ export function parseOption(text: string): PanelOption {
225
225
  return split ? { label: split[1]!.trim(), description: split[2]!.trim() } : { label: flat, description: "" };
226
226
  }
227
227
 
228
- /** The option the asker recommends: the one marked `(Recommended)`, else the first. */
228
+ /** The option the asker recommends: only the one marked `(Recommended)`; nothing is implied by order. */
229
229
  export function recommendedOption(question: AskedQuestion): PanelOption | undefined {
230
- return question.options.find((option) => /\(recommended\)/i.test(option.label)) ?? question.options[0];
230
+ return question.options.find((option) => /\(recommended\)/i.test(option.label));
231
231
  }
232
232
 
233
233
  /** An option's label without its `(Recommended)` marker. */
@@ -171,7 +171,7 @@ export function splitQuestion(input: { stepCount: number; proposal: SplitProposa
171
171
  last ? "This is the last revision: take it, or keep the plan whole." : "Type what to change (for example *merge 2 and 3*) to revise it.",
172
172
  ].join("\n\n"),
173
173
  options: [
174
- { label: `${splitLabel(count)} (Recommended)`, description: "Each part is saved as its own pending task, in order, knowing the others.", preview: splitPreview(input.proposal, input.steps) },
174
+ { label: splitLabel(count), description: "Each part is saved as its own pending task, in order, knowing the others.", preview: splitPreview(input.proposal, input.steps) },
175
175
  { label: "Keep it as one task", description: `One task with all ${input.stepCount} steps.` },
176
176
  ],
177
177
  };
package/src/pi/tools.ts CHANGED
@@ -27,7 +27,7 @@ const OrchestrateSchema = Type.Object({
27
27
  action: StringEnum(ORCHESTRATE_ACTIONS, { description: "Workflow step to run" }),
28
28
  taskId: Type.Optional(Type.String({ description: "Task id; defaults to the active task" })),
29
29
  question: Type.Optional(Type.String({ description: "clarify: question for the user" })),
30
- options: Type.Optional(Type.Array(Type.String(), { description: "clarify: optional answer choices; put your recommended one first and mark it (Recommended)" })),
30
+ options: Type.Optional(Type.Array(Type.String(), { description: "clarify: optional answer choices, neutral and unranked; mark one (Recommended) only when the answer is quite obvious" })),
31
31
  domains: Type.Optional(Type.Array(Type.String(), { description: "scout: any of designer, backend, qa" })),
32
32
  instruction: Type.Optional(Type.String({ description: "scout/research: a self-contained brief: the specific questions, where to look, the answer format you want (paths, names, versions, evidence) and what you will do with it. The agent may be a small model: assume nothing" })),
33
33
  proposal: Type.Optional(Type.String({ description: "propose: the user-facing proposal as a short `- ` bullet list, one line per change" })),