fix: inject observability warnings into agent prompt for enforcement (#174)
emitObservabilityWarnings only called ctx.ui.notify — the agent never saw the warnings and ignored them entirely. Validator caught real issues (missing observability sections, placeholder diagnostics) but had zero enforcement. Rename to collectObservabilityWarnings (returns issues), add buildObservabilityRepairBlock to format issues as actionable prompt instructions. Appended to the unit prompt so the agent reads flagged files and fixes gaps before proceeding with the unit. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
788c356a25
commit
498614c95f
1 changed files with 42 additions and 9 deletions
|
|
@ -1262,7 +1262,7 @@ async function dispatchNextUnit(
|
|||
return;
|
||||
}
|
||||
|
||||
await emitObservabilityWarnings(ctx, unitType, unitId);
|
||||
const observabilityIssues = await collectObservabilityWarnings(ctx, unitType, unitId);
|
||||
|
||||
// Idempotency: skip units already completed in a prior session.
|
||||
const idempotencyKey = `${unitType}/${unitId}`;
|
||||
|
|
@ -1402,6 +1402,13 @@ async function dispatchNextUnit(
|
|||
}
|
||||
}
|
||||
|
||||
// Inject observability repair instructions so the agent fixes gaps before
|
||||
// proceeding with the unit (see #174).
|
||||
const repairBlock = buildObservabilityRepairBlock(observabilityIssues);
|
||||
if (repairBlock) {
|
||||
finalPrompt = `${finalPrompt}${repairBlock}`;
|
||||
}
|
||||
|
||||
// Switch model if preferences specify one for this unit type
|
||||
// Try primary model, then fallbacks in order if setting fails
|
||||
const modelConfig = resolveModelWithFallbacksForUnit(unitType);
|
||||
|
|
@ -2365,17 +2372,17 @@ function ensurePreconditions(
|
|||
|
||||
// ─── Diagnostics ──────────────────────────────────────────────────────────────
|
||||
|
||||
async function emitObservabilityWarnings(
|
||||
async function collectObservabilityWarnings(
|
||||
ctx: ExtensionContext,
|
||||
unitType: string,
|
||||
unitId: string,
|
||||
): Promise<void> {
|
||||
): Promise<import("./observability-validator.ts").ValidationIssue[]> {
|
||||
const parts = unitId.split("/");
|
||||
const mid = parts[0];
|
||||
const sid = parts[1];
|
||||
const tid = parts[2];
|
||||
|
||||
if (!mid || !sid) return;
|
||||
if (!mid || !sid) return [];
|
||||
|
||||
let issues = [] as Awaited<ReturnType<typeof validatePlanBoundary>>;
|
||||
|
||||
|
|
@ -2387,12 +2394,38 @@ async function emitObservabilityWarnings(
|
|||
issues = await validateCompleteBoundary(basePath, mid, sid);
|
||||
}
|
||||
|
||||
if (issues.length === 0) return;
|
||||
if (issues.length > 0) {
|
||||
ctx.ui.notify(
|
||||
`Observability check (${unitType}) found ${issues.length} warning${issues.length === 1 ? "" : "s"}:\n${formatValidationIssues(issues)}`,
|
||||
"warning",
|
||||
);
|
||||
}
|
||||
|
||||
ctx.ui.notify(
|
||||
`Observability check (${unitType}) found ${issues.length} warning${issues.length === 1 ? "" : "s"}:\n${formatValidationIssues(issues)}`,
|
||||
"warning",
|
||||
);
|
||||
return issues;
|
||||
}
|
||||
|
||||
function buildObservabilityRepairBlock(issues: import("./observability-validator.ts").ValidationIssue[]): string {
|
||||
if (issues.length === 0) return "";
|
||||
const items = issues.map(issue => {
|
||||
const fileName = issue.file.split("/").pop() || issue.file;
|
||||
let line = `- **${fileName}**: ${issue.message}`;
|
||||
if (issue.suggestion) line += ` → ${issue.suggestion}`;
|
||||
return line;
|
||||
});
|
||||
return [
|
||||
"",
|
||||
"---",
|
||||
"",
|
||||
"## Pre-flight: Observability gaps to fix FIRST",
|
||||
"",
|
||||
"The following issues were detected in plan/summary files for this unit.",
|
||||
"**Read each flagged file, apply the fix described, then proceed with the unit.**",
|
||||
"",
|
||||
...items,
|
||||
"",
|
||||
"---",
|
||||
"",
|
||||
].join("\n");
|
||||
}
|
||||
|
||||
async function recoverTimedOutUnit(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue