Combined output of multiple parallel codex-rescue runs that produced working-tree edits but didn't commit. Tasks contributing: - prefs: per-provider model allow-list (provider_model_allow) — manual - TUI scroll + unresponsive (a7884d1a / bt3fpn4y2) - planningMeeting required (aa09e904 / br127l763) - Logs UX 4-pack (a5c65314 / btcplhu7f) - Gate auto-resolve + completion nudge (ae4c8b64 / bw1w1fjkp) - sf_task_complete atomic + retry (a7a079b4 / b20cy5owv) - Multi-model meeting + minimax M2.7 + draft promotion (a756faac / task-moifjknd-lwjc98) - Per-role slice prompts (a94c3e1a) - Per-role vision-meeting prompts (afd165a0 / task-moifple5-lcwtjl) - Schema sweep (ac994b1e / task-moifq7pu-83coqz) - Flow audit (ad26ecfd / bttj4vrqm) Typecheck passes. Tests not run as a full suite — spot-check after merge. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Co-Authored-By: OpenAI Codex <noreply@openai.com>
144 lines
5.6 KiB
TypeScript
144 lines
5.6 KiB
TypeScript
export interface AdversarialReviewRecord {
|
|
partner: string;
|
|
combatant: string;
|
|
architect: string;
|
|
}
|
|
|
|
export type PlanningMeetingRoute = "discussing" | "researching" | "planning";
|
|
|
|
export interface PlanningMeetingRecord {
|
|
trigger: string;
|
|
pm: string;
|
|
userAdvocate?: string;
|
|
customerPanel?: string;
|
|
business?: string;
|
|
researcher: string;
|
|
deliveryLead?: string;
|
|
partner: string;
|
|
combatant: string;
|
|
architect: string;
|
|
moderator: string;
|
|
recommendedRoute: PlanningMeetingRoute;
|
|
confidenceSummary: string;
|
|
}
|
|
|
|
export interface SlicePlanQualityCheck {
|
|
issues: string[];
|
|
}
|
|
|
|
const PLACEHOLDER_VALUES = new Set([
|
|
"",
|
|
"not provided.",
|
|
"missing adversarial review.",
|
|
"missing partner review.",
|
|
"missing combatant review.",
|
|
"missing architect review.",
|
|
]);
|
|
|
|
function isMeaningfulReviewBody(value: string | null | undefined): boolean {
|
|
const normalized = (value ?? "").trim().toLowerCase();
|
|
return normalized.length > 0 && !PLACEHOLDER_VALUES.has(normalized);
|
|
}
|
|
|
|
function extractSection(content: string, heading: string): string {
|
|
const lines = content.split("\n");
|
|
const start = lines.findIndex((line) => line.trim() === `## ${heading}`);
|
|
if (start === -1) return "";
|
|
|
|
let end = lines.length;
|
|
for (let index = start + 1; index < lines.length; index += 1) {
|
|
if (/^##\s+/.test(lines[index])) {
|
|
end = index;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return lines.slice(start + 1, end).join("\n").trim();
|
|
}
|
|
|
|
function extractSubsection(content: string, heading: string): string {
|
|
const lines = content.split("\n");
|
|
const start = lines.findIndex((line) => line.trim() === `### ${heading}`);
|
|
if (start === -1) return "";
|
|
|
|
let end = lines.length;
|
|
for (let index = start + 1; index < lines.length; index += 1) {
|
|
if (/^###\s+/.test(lines[index]) || /^##\s+/.test(lines[index])) {
|
|
end = index;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return lines.slice(start + 1, end).join("\n").trim();
|
|
}
|
|
|
|
export function hasCompleteAdversarialReview(review: Partial<AdversarialReviewRecord> | null | undefined): boolean {
|
|
return isMeaningfulReviewBody(review?.partner)
|
|
&& isMeaningfulReviewBody(review?.combatant)
|
|
&& isMeaningfulReviewBody(review?.architect);
|
|
}
|
|
|
|
export function hasStructuredPlanningMeeting(meeting: Partial<PlanningMeetingRecord> | null | undefined): meeting is PlanningMeetingRecord {
|
|
if (!meeting) return false;
|
|
const route = meeting.recommendedRoute;
|
|
return isMeaningfulReviewBody(meeting.trigger)
|
|
&& isMeaningfulReviewBody(meeting.pm)
|
|
&& isMeaningfulReviewBody(meeting.researcher)
|
|
&& isMeaningfulReviewBody(meeting.partner)
|
|
&& isMeaningfulReviewBody(meeting.combatant)
|
|
&& isMeaningfulReviewBody(meeting.architect)
|
|
&& isMeaningfulReviewBody(meeting.moderator)
|
|
&& isMeaningfulReviewBody(meeting.confidenceSummary)
|
|
&& (route === "discussing" || route === "researching" || route === "planning");
|
|
}
|
|
|
|
export function inspectSlicePlanMarkdown(content: string): SlicePlanQualityCheck {
|
|
const issues: string[] = [];
|
|
const adversarialSection = extractSection(content, "Adversarial Review");
|
|
if (!adversarialSection) {
|
|
issues.push("missing adversarial review");
|
|
return { issues };
|
|
}
|
|
|
|
const partner = extractSubsection(adversarialSection, "Partner Review");
|
|
const combatant = extractSubsection(adversarialSection, "Combatant Review");
|
|
const architect = extractSubsection(adversarialSection, "Architect Review");
|
|
|
|
if (!isMeaningfulReviewBody(partner)) issues.push("missing partner review");
|
|
if (!isMeaningfulReviewBody(combatant)) issues.push("missing combatant review");
|
|
if (!isMeaningfulReviewBody(architect)) issues.push("missing architect review");
|
|
|
|
const planningMeeting = extractSection(content, "Planning Meeting");
|
|
if (planningMeeting) {
|
|
const trigger = extractSubsection(planningMeeting, "Trigger");
|
|
const pm = extractSubsection(planningMeeting, "Product Manager");
|
|
const researcher = extractSubsection(planningMeeting, "Researcher");
|
|
const meetingPartner = extractSubsection(planningMeeting, "Partner");
|
|
const meetingCombatant = extractSubsection(planningMeeting, "Combatant");
|
|
const meetingArchitect = extractSubsection(planningMeeting, "Architect");
|
|
const moderator = extractSubsection(planningMeeting, "Moderator");
|
|
const route = extractSubsection(planningMeeting, "Recommended Route").toLowerCase();
|
|
const confidence = extractSubsection(planningMeeting, "Confidence");
|
|
|
|
if (!isMeaningfulReviewBody(trigger)) issues.push("missing planning meeting trigger");
|
|
if (!isMeaningfulReviewBody(pm)) issues.push("missing planning meeting pm review");
|
|
if (!isMeaningfulReviewBody(researcher)) issues.push("missing planning meeting researcher review");
|
|
if (!isMeaningfulReviewBody(meetingPartner)) issues.push("missing planning meeting partner review");
|
|
if (!isMeaningfulReviewBody(meetingCombatant)) issues.push("missing planning meeting combatant review");
|
|
if (!isMeaningfulReviewBody(meetingArchitect)) issues.push("missing planning meeting architect review");
|
|
if (!isMeaningfulReviewBody(moderator)) issues.push("missing planning meeting moderator decision");
|
|
if (!isMeaningfulReviewBody(confidence)) issues.push("missing planning meeting confidence");
|
|
if (route && route !== "planning" && route !== "researching" && route !== "discussing") {
|
|
issues.push("invalid planning meeting route");
|
|
} else if (route && route !== "planning") {
|
|
issues.push(`planning meeting routed back to ${route}`);
|
|
}
|
|
}
|
|
|
|
return { issues };
|
|
}
|
|
|
|
export function getSlicePlanBlockingIssue(content: string): string | null {
|
|
const check = inspectSlicePlanMarkdown(content);
|
|
return check.issues[0] ?? null;
|
|
}
|