mirror of
https://github.com/garrytan/gstack.git
synced 2026-10-09 12:51:54 +02:00
test(design-floor): answer the seed-declared all-seven 0D focus menu while it is pending
The actor declares 'Design: review all seven dimensions', but its picker reused designReviewSetupAUQ, which only matches already-answered calls (and a narrower header/label set), so the pending D1 focus menu was never answered and the case waited out its 609 s deadline. The skill's Step 0D requires asking; the fixture now answers it.
This commit is contained in:
1 parent
3a888896db
commit
41dca7609d
3 files changed
+61
-38
No files matched your search
@@ -3123,45 +3123,29 @@ export const engStep0Boundary: Step0BoundaryPredicate = (fp) =>
|
||||
// plan-eng-review-idempotency, plan-eng-review-todos-e2e-concurrent.
|
||||
/gstack-qid:\s*(?:plan-)?eng-review-/i.test(fp.promptSnippet);
|
||||
|
||||
/** Completed plan-wide focus and local-learnings choices remain setup, even when asked late. */
|
||||
export const designReviewSetupAUQ: Step0BoundaryPredicate = (fp) => {
|
||||
const call = fp.nativeCall;
|
||||
if (call?.answered !== true || call.failed !== false || !call.sessionId || !call.toolUseId ||
|
||||
call.questions.length !== 1 || !Array.isArray(call.unansweredQuestionIndices) || call.unansweredQuestionIndices.length ||
|
||||
!Number.isFinite(Date.parse(call.answeredAt ?? '')) || fp.signature !== `${call.sessionId}:${call.toolUseId}` ||
|
||||
(fp.nativeQuestionIndex !== undefined && fp.nativeQuestionIndex !== 0)) return false;
|
||||
const q = call.questions[0]!;
|
||||
if (q.multiSelect || q.options.length !== 2 || new Set(q.options.map(o => o.label)).size !== 2 ||
|
||||
Object.keys(call.answers ?? {}).length !== 1 || q.options.filter(o => o.label === call.answers?.[q.question]).length !== 1 ||
|
||||
fp.options.length !== 2 || !fp.options.every((o, i) => o.index === i + 1 && o.label === q.options[i]!.label)) return false;
|
||||
/**
|
||||
* The seed declares "Design: review all seven dimensions" for the pending Step 0D
|
||||
* focus menu. Pick its single all-seven option only when every other option
|
||||
* narrows the review and the brief approves no product action.
|
||||
*/
|
||||
export function pickDesignFocusAll(q: NativePlanQuestionCall['questions'][number]): number | null {
|
||||
if (q.multiSelect || q.options.length < 2 || q.options.length > 4 || new Set(q.options.map(o => o.label)).size !== q.options.length) return null;
|
||||
const text = q.question.trim();
|
||||
const title = text.split(/\r?\n/, 1)[0]!.replace(/^D[1-9]\d*\s*[—–:-]\s*/i, '');
|
||||
const sources = [...text.matchAll(/^Project\/branch\/task:\s*([^\n]+)$/gm)];
|
||||
const source = sources[0]?.[1] ?? '';
|
||||
// Setup never approves another product action. Quoted examples and negative
|
||||
// consequences are explanatory; current imperative clauses remain decisions.
|
||||
const explanatory = [text, ...q.options.map(o => o.description ?? '')].join('\n')
|
||||
.replace(/`+[^`]*`+|"[^"\n]*"|“[^”\n]*”|‘[^’\n]*’/g, '')
|
||||
.replace(/[✅❌*]/g, '');
|
||||
if (/(?:^|[.!?;:\n]|\b(?:and|while))\s*(?:(?:also|please|then|now)\s+)*(?:approv(?:e|ing)|deploy(?:ing)?|implement(?:ing)?|ship(?:ping)?|merg(?:e|ing)|delet(?:e|ing))\b/im.test(explanatory)) return false;
|
||||
if (sources.length !== 1 || (text.match(/\?/g)?.length ?? 0) !== 1 || /```|~~~|^\s*>/m.test(text) ||
|
||||
!/\bplan-design-review of PLAN\.md\b/i.test(source) ||
|
||||
/\b(?:historical|archived|quoted|example|foreign|other|another|previous)\b/i.test(source)) return false;
|
||||
const labels = q.options.map(o => o.label.trim().replace(/^[A-Z][).:]\s+/i, '')
|
||||
.replace(/\s*\(recommended\)\s*$/i, ''));
|
||||
if (/^(?:Learnings|Cross-project)$/i.test(q.header.trim()) &&
|
||||
/^Enable cross[- ]project learnings(?: search)?\?$/i.test(title) &&
|
||||
labels.some(label => /^Enable cross[- ]project learnings$/i.test(label)) &&
|
||||
labels.some(label => /^Keep learnings project[- ]scoped(?: only)?$/i.test(label))) {
|
||||
// Reuse the existing native cross-project premise/owned answer classifier.
|
||||
return engSetupAUQ(fp);
|
||||
}
|
||||
return /^(?:Focus|Review focus)$/i.test(q.header.trim()) &&
|
||||
/^Review all 7 (?:design )?(?:dimensions|passes),? or focus(?: on (?:specific areas|a subset))?\?$/i.test(title) &&
|
||||
/^ELI10:\s*I['’]ve rated this plan (?:10(?:\.0+)?|[0-9](?:\.\d+)?)\/10 on design completeness\./mi.test(text) &&
|
||||
labels.some(label => /^(?:Review )?All 7 (?:design )?(?:dimensions|passes)$/i.test(label)) &&
|
||||
labels.some(label => /^(?:Only (?:the )?[1-6](?: listed)? (?:gaps|areas|dimensions|passes)|Focus on (?:specific areas|a subset))$/i.test(label));
|
||||
};
|
||||
.replace(/`+[^`]*`+|"[^"\n]*"|“[^”\n]*”|‘[^’\n]*’/g, '').replace(/[✅❌*]/g, '');
|
||||
if (!/^Review all (?:7|seven) (?:design )?(?:dimensions|passes),? or focus(?: on [^?\n]+)?\?$/i.test(title) ||
|
||||
sources.length !== 1 || !/\bplan-design-review of PLAN\.md\b/i.test(sources[0]![1]!) ||
|
||||
/\b(?:historical|archived|quoted|example|foreign|other|another|previous)\b/i.test(sources[0]![1]!) ||
|
||||
(text.match(/\?/g)?.length ?? 0) !== 1 || /```|~~~|^\s*>/m.test(text) ||
|
||||
!/^ELI10:\s*I['’]ve rated this plan (?:10(?:\.0+)?|[0-9](?:\.\d+)?)\/10 on design completeness\./mi.test(text) ||
|
||||
/(?:^|[.!?;:\n]|\b(?:and|while))\s*(?:(?:also|please|then|now)\s+)*(?:approv(?:e|ing)|deploy(?:ing)?|implement(?:ing)?|ship(?:ping)?|merg(?:e|ing)|delet(?:e|ing))\b/im.test(explanatory)) return null;
|
||||
const labels = q.options.map(o => o.label.trim().replace(/^[A-Z][).:]\s+/i, '').replace(/\s*\(recommended\)\s*$/i, ''));
|
||||
const all = labels.flatMap((label, i) => /^(?:Review )?All (?:7|seven) (?:design )?(?:dimensions|passes)$/i.test(label) ? [i + 1] : []);
|
||||
if (all.length !== 1 || labels.some((label, i) => i + 1 !== all[0] && !/^(?:Only|Focus)\b/i.test(label))) return null;
|
||||
return all[0]!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawn `claude --permission-mode plan` in a real PTY and return a session
|
||||
@@ -4931,11 +4915,9 @@ export async function runPlanSkillFloorCheck(opts: {
|
||||
const question = pendingQuestion.questions[index]!;
|
||||
const key = `${pendingQuestion.sessionId}:${pendingQuestion.toolUseId}`;
|
||||
const chosen = setupChoices.get(key) ?? new Set<number>();
|
||||
const allDesign = opts.skillName === 'plan-design-review' && designReviewSetupAUQ(fp)
|
||||
? question.options.flatMap((option, i) => /^(?:Review )?All 7 (?:design )?(?:dimensions|passes)(?:\s*\(recommended\))?$/i.test(option.label.trim()) ? [i + 1] : []) : [];
|
||||
const pick = pickPlanFloorMode(opts.skillName, question) ?? planCountPrerequisitePick(fp, fp)
|
||||
?? (opts.skillName === 'plan-devex-review' ? pickPlanFloorProductType(question, opts.productType) : null)
|
||||
?? (allDesign.length === 1 ? allDesign[0]! : null);
|
||||
?? (opts.skillName === 'plan-design-review' ? pickDesignFocusAll(question) : null);
|
||||
if (pick !== null) {
|
||||
if (!chosen.has(index)) {
|
||||
session.send(planCountQuestionInput(viewport, fp, pick));
|
||||
|
||||
Reference in new issue
Block a user