feat(iit): harden QC pipeline consistency and release artifacts

Implement IIT quality workflow hardening across eQuery deduplication, guard metadata validation, timeline/readability improvements, and chat evidence fallbacks, then synchronize release and development documentation for deployment handoff.

Includes migration/scripts for open eQuery dedupe guards, orchestration/status semantics, report/tool readability fixes, and updated module status plus deployment checklist.

Made-with: Cursor
This commit is contained in:
2026-03-08 21:54:35 +08:00
parent ac724266c1
commit a666649fd4
57 changed files with 28637 additions and 316 deletions

View File

@@ -0,0 +1,114 @@
/**
* 引擎级 guard smoke test与项目配置无关
*
* 注意:
* - 本脚本只验证 HardRuleEngine 的通用 guard 机制是否生效
* - 不代表任何具体项目规则配置
* - 项目级回归请使用 regression_hardrule_guards_by_project.ts
*/
import assert from 'node:assert';
import { HardRuleEngine, type QCRule } from '../src/modules/iit-manager/engines/HardRuleEngine.js';
function runCase(name: string, rules: QCRule[], data: Record<string, any>, expectedStatus: 'PASS' | 'FAIL' | 'WARNING') {
const engine = new HardRuleEngine('regression-project');
const result = engine.executeWithRules('R1', data, rules);
assert.strictEqual(result.overallStatus, expectedStatus, `${name} 期望 ${expectedStatus},实际 ${result.overallStatus}`);
console.log(`${name}: ${result.overallStatus}`);
}
async function main() {
const rules: QCRule[] = [
{
id: 'r1',
name: 'date consistency check A',
field: ['visiting_date', 'date_of_signature'],
logic: { '<': [{ var: 'visiting_date' }, { var: 'date_of_signature' }] },
message: 'date ordering failed',
severity: 'error',
category: 'D1',
metadata: { guardType: 'date_not_before_or_equal' },
},
{
id: 'r2',
name: 'date consistency check B',
field: ['date_of_assessment_sf_mpq_scale', 'visiting_date'],
logic: { '!=': [{ var: 'date_of_assessment_sf_mpq_scale' }, { var: 'visiting_date' }] },
message: 'date mismatch',
severity: 'warning',
category: 'D3',
metadata: { guardType: 'skip_if_any_missing' },
},
{
id: 'r3',
name: 'all inclusion criteria check',
field: ['inclusion_criteria1', 'inclusion_criteria2', 'inclusion_criteria3', 'inclusion_criteria4', 'inclusion_criteria5'],
logic: { '==': [1, 0] }, // 故意构造为失败,验证 guard 能兜底
message: 'inclusion not all met',
severity: 'warning',
category: 'D1',
metadata: { guardType: 'pass_if_all_ones' },
},
{
id: 'r4',
name: 'enrollment exclusion conflict check',
field: ['enrollment_status', 'exclusion_criteria1', 'exclusion_criteria2'],
logic: { '==': [1, 0] }, // 故意构造为失败,验证 guard 能兜底
message: 'enrollment conflict',
severity: 'error',
category: 'D1',
metadata: { guardType: 'pass_if_exclusion_all_zero' },
},
];
runCase(
'同日访视不应误判早于',
[rules[0]],
{ visiting_date: '2024-03-27', date_of_signature: '2024-03-27' },
'PASS',
);
runCase(
'评估日期缺失不应判不一致',
[rules[1]],
{ date_of_assessment_sf_mpq_scale: '', visiting_date: '2024-03-27' },
'PASS',
);
runCase(
'纳入标准全1应通过',
[rules[2]],
{ inclusion_criteria1: 1, inclusion_criteria2: 1, inclusion_criteria3: 1, inclusion_criteria4: 1, inclusion_criteria5: 1 },
'PASS',
);
runCase(
'排除标准全0应通过',
[rules[3]],
{ enrollment_status: 1, exclusion_criteria1: 0, exclusion_criteria2: 0 },
'PASS',
);
runCase(
'无guard普通规则失败应保持失败',
[
{
id: 'r5',
name: 'plain range check',
field: 'age',
logic: { '>=': [{ var: 'age' }, 18] },
message: 'age too small',
severity: 'error',
category: 'D1',
},
],
{ age: 10 },
'FAIL',
);
}
main().catch((e) => {
console.error(e);
process.exit(1);
});