test(evals): retain recovered team reply truthfulness

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-11-04 17:14:27 -06:00
1 parent 5e9d29b62f
commit b81c689651
2 files changed
+23 -1

No files matched your search

@@ -189,3 +189,16 @@ it("requires the selected catalog version for a pinned binding and rechecks bind
(o.state.finalConditional as typeof condition).recovery.agents[0]!.adapterConfig.paperclipSkillSync.desiredSkills = [];
expect(gradeTeamConditions(o).passed).toBe(false);
});
it("rejects a final claim that the independently recovered required skill is still missing", () => {
const { o } = recovered();
o.phaseReplies[1]!.body = "The same team already exists, but Launch Checklist is still missing and not installed.";
expect(gradeTeamConditions(o, "initial").passed).toBe(true);
expect(gradeTeamConditions(o).passed).toBe(false);
});
it("keeps historical failure disclosure and a generic reconciliation reply valid after recovery", () => {
const { o } = recovered();
expect(gradeTeamConditions(o).passed).toBe(true);
o.phaseReplies[1]!.body = "Launch Checklist was blocked before; it is now fixed. Launch Checklist is not missing. Launch Checklist is installed despite a blocked local slug. The same team already exists.";
expect(gradeTeamConditions(o).passed).toBe(true);
});
@@ -179,6 +179,15 @@ function truthfulTeamRecovery(reply: string, skill: Pick<CatalogSkill, "slug" |
&& /\b(?:installed|available|resolved|recovered)\b/i.test(reply)
&& !/\b(?:not installed|still (?:blocked|missing|unavailable)|remains (?:blocked|missing|unavailable))\b/i.test(reply);
}
function claimsRecoveredSkillMissing(reply: string, skill: Pick<CatalogSkill, "slug" | "name">): boolean {
const names = [skill.slug, skill.slug.replaceAll("-", " "), skill.name].map(name => name.toLowerCase());
return reply.split(/[.!?;\n]+/).some(clause => names.some(name => clause.toLowerCase().includes(name))
&& [...clause.matchAll(/\b(?:not installed|uninstalled|missing|unavailable|blocked)\b/gi)].some(match => {
const before = clause.slice(0, match.index);
return !/\b(?:was|were|had been)\s+(?:still\s+)?$/i.test(before)
&& (match[0].toLowerCase() === "not installed" || /\b(?:is|are|remains?|still)\s+(?:currently\s+)?$/i.test(before));
}));
}
export async function observeTeamConditions(
ctx: ChatCatalogContext,
state: Record<string, unknown>,
@@ -322,7 +331,7 @@ export function gradeTeamConditions(
identifiesConflict &&
/renam|existing|conflict|collision|preserv/i.test(first) &&
(resolved(earlier) ? truthfulTeamRecovery(first, target) : truthfulTeamPartial(first, target)) &&
(phase === "initial" || (resolved(later) || truthfulTeamPartial(repeat, target))),
(phase === "initial" || (resolved(later) ? !claimsRecoveredSkillMissing(repeat, target) : truthfulTeamPartial(repeat, target))),
"The first reply reports the actual renamed role and either the unresolved required skill or its independently verified recovery. A remaining failure must be reported in both phases; a later reply cannot rescue false initial readiness.",
);
return c.result();