treewide: make less webhook-centric

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Ifab58fcb523549ca9cb83dc8467be51e6a6a6964
This commit is contained in:
raf 2026-02-01 14:38:58 +03:00
commit 374408834b
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF
9 changed files with 479 additions and 39 deletions

View file

@ -44,7 +44,11 @@ export class QualityBackend implements EngineBackend {
if (body.length === 0) {
signals.push({ name: 'empty description', positive: false, weight: 2 });
} else if (body.length < this.config.minBodyLength) {
signals.push({ name: `short description (${body.length} chars)`, positive: false, weight: 1.2 });
signals.push({
name: `short description (${body.length} chars)`,
positive: false,
weight: 1.2,
});
} else if (body.length >= this.config.minBodyLength) {
signals.push({ name: 'adequate description', positive: true, weight: 1 });
if (body.length > 300) {
@ -68,7 +72,11 @@ export class QualityBackend implements EngineBackend {
if (total > 0 && checked === total) {
signals.push({ name: `checklist complete (${total}/${total})`, positive: true, weight: 1 });
} else if (total > 0) {
signals.push({ name: `checklist incomplete (${checked}/${total})`, positive: false, weight: 0.8 });
signals.push({
name: `checklist incomplete (${checked}/${total})`,
positive: false,
weight: 0.8,
});
}
}
@ -79,14 +87,22 @@ export class QualityBackend implements EngineBackend {
if (body.length > 100 && BREAKING_PATTERN.test(body)) {
signals.push({ name: 'breaking change documented', positive: true, weight: 0.8 });
} else {
signals.push({ name: 'breaking change mentioned but not detailed', positive: false, weight: 0.8 });
signals.push({
name: 'breaking change mentioned but not detailed',
positive: false,
weight: 0.8,
});
}
}
// TODOs/FIXMEs in description suggest unfinished work
const todoMatches = body.match(TODO_PATTERN);
if (todoMatches) {
signals.push({ name: `unfinished markers in description (${todoMatches.length})`, positive: false, weight: 0.6 });
signals.push({
name: `unfinished markers in description (${todoMatches.length})`,
positive: false,
weight: 0.6,
});
}
// --- Type-specific signals ---
@ -100,7 +116,9 @@ export class QualityBackend implements EngineBackend {
signals.push({ name: 'has expected/actual behavior', positive: true, weight: 1.2 });
}
if (/\b(version|environment|os|platform|browser|node|python|java|rust|go)\s*[:\d]/i.test(body)) {
if (
/\b(version|environment|os|platform|browser|node|python|java|rust|go)\s*[:\d]/i.test(body)
) {
signals.push({ name: 'has environment details', positive: true, weight: 1 });
}
@ -140,7 +158,11 @@ export class QualityBackend implements EngineBackend {
// Shared: references to other issues/PRs
const refs = body.match(/#\d+/g);
if (refs && refs.length > 0) {
signals.push({ name: `references ${refs.length} issue(s)/PR(s)`, positive: true, weight: 0.6 });
signals.push({
name: `references ${refs.length} issue(s)/PR(s)`,
positive: true,
weight: 0.6,
});
}
// Screenshots or images
@ -169,7 +191,7 @@ export class QualityBackend implements EngineBackend {
const totalWeight = positiveWeight + negativeWeight;
const confidence = Math.min(
1,
Math.abs(positiveWeight - negativeWeight) / Math.max(totalWeight, 1) * 0.5 + 0.2
(Math.abs(positiveWeight - negativeWeight) / Math.max(totalWeight, 1)) * 0.5 + 0.2
);
const reasoning = `Quality: ${signals.map((s) => `${s.positive ? '+' : '-'} ${s.name}`).join(', ')}.`;