| 237 |
237 |
|
| 238 |
238 |
const prov = existing ? await loadCurrentProvenance(tx, "project", existingId!) : []; |
| 239 |
239 |
const id = existing ? String(existing.id) : newId("project"); |
|
240 |
+ // a project hidden by the automated repair re-qualifies when a re-extraction yields a physical class with strong evidence |
|
241 |
+ // (human decisions — resolved_by <> 'quality-apply' / 'system' — are never reversed) |
|
242 |
+ if (existing && existing.hidden && physical && p.evidenceLevel === "strong" && !ctx.run.dryRun) { |
|
243 |
+ const auto = await tx.execute(sql`select 1 from quality_flags where entity_type = 'project' and entity_id = ${id} and code = 'project_false_positive' and resolved_by in ('quality-apply', 'system') limit 1`); |
|
244 |
+ const human = await tx.execute(sql`select 1 from quality_flags where entity_type = 'project' and entity_id = ${id} and code = 'project_false_positive' and resolved_by not in ('quality-apply', 'system') limit 1`); |
|
245 |
+ if (auto.length && !human.length) { |
|
246 |
+ await tx.execute(sql`update projects set hidden = false, updated_at = now() where id = ${id}`); |
|
247 |
+ await tx.execute(sql`update quality_flags set resolution = 'auto: re-qualified by re-extraction (physical class, strong evidence)', resolved_at = now() where entity_type = 'project' and entity_id = ${id} and code = 'project_false_positive'`); |
|
248 |
+ existing.hidden = false; |
|
249 |
+ ctx.stats.projectsRequalified = (ctx.stats.projectsRequalified ?? 0) + 1; |
|
250 |
+ } |
|
251 |
+ } |
| 240 |
252 |
const before: Row = existing ? { ...existing } : {}; |
| 241 |
253 |
const next: Row = existing ? { ...existing } : { id, status: "announced", geoPrecision: "unknown", isAi: false, confidence: "moderate", externalIds: {}, aiEvidence: "unknown", hidden: false, reviewPriority: 0 }; |
| 242 |
254 |
const observed: ObservedField[] = []; |
| 243 |
255 |
|