Recognize bounded qualifiers on the exact required-skill subject

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-11-06 03:19:36 -06:00
1 parent 537f807a12
commit f60ad9c6ae
2 files changed
+17 -1

No files matched your search

@@ -534,3 +534,19 @@ it("rejects a current unattached claim when independent saved recovery is proven
expect(gradeTeamConditions(o, phase === 0 ? "initial" : "complete").passed).toBe(false);
}
});
it("binds ordinary skill qualifiers to the exact required skill across missing and recovery checks",()=>{
const target={slug:"doc-maintenance",name:"doc-maintenance"};
for(const qualifier of ["catalog","required catalog","imported","bundled"]){
const partial="The `doc-maintenance` "+qualifier+" skill is unresolved because a company-owned skill already uses that slug; I preserved the existing skill.";
expect(truthfulTeamPartial(partial,target,true),partial).toBe(true);
expect(truthfulTeamPartial(partial+" The doc-maintenance "+qualifier+" skill is now installed.",target,true)).toBe(false);
expect(truthfulTeamPartial("A different "+qualifier+" skill is unresolved because its slug conflicts.",target,true)).toBe(false);
expect(truthfulTeamPartial("Earlier, the doc-maintenance "+qualifier+" skill was unresolved because its slug conflicted.",target,true)).toBe(false);
for(const phase of [0,1]){
const {o}=recovered();
o.phaseReplies[phase]!.body="The existing CTO was preserved and the new role renamed CTO 2. Launch Checklist "+qualifier+" skill is still missing.";
expect(gradeTeamConditions(o,phase===0?"initial":"complete").passed).toBe(false);
}
}
});
@@ -206,7 +206,7 @@ function negatedTeamRecovery(before: string): boolean {
return /\b(?:not|never|isn.t|aren.t|wasn.t|weren.t|hasn.t|haven.t)\s+(?:(?:be|been|get|yet|currently|still|successfully|fully|completely)\s+){0,2}$/i.test(before.replace(/[*_`]+\s*$/, ""));
}
function teamSkillSubject(skill: Pick<CatalogSkill, "slug" | "name">): string {
return "[*_`]*(?:" + [skill.slug, skill.slug.replaceAll("-", " "), skill.name].map(name => name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|") + ")[*_`]*";
return "[*_`]*(?:" + [skill.slug, skill.slug.replaceAll("-", " "), skill.name].map(name => name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|") + ")[*_`]*(?:\\s+(?:(?:required|catalog|imported|bundled)\\s+){1,3}skill)?";
}
function historicalTeamSkillClause(clause: string, skill: Pick<CatalogSkill, "slug" | "name">): boolean {
const subject = new RegExp(teamSkillSubject(skill), "i").exec(clause);