# LSFX Mock Rule Hit Mode Backend Implementation Plan > **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** 为 `lsfx-mock-server` 增加可通过命令行切换的规则命中模式,在默认保持稳定随机子集命中的前提下,支持切换为“全部兼容规则命中”。 **Architecture:** 保持现有 `FileService -> StatementService -> FileRecord 缓存` 主链路不变,只在启动层新增命令行参数解析,在配置层新增统一模式值,在规则计划层新增 `subset/all` 两种编排路径。`all` 模式不做字面全开,而是通过显式互斥组裁剪产出“全部兼容规则命中”计划,避免样本语义冲突。 **Tech Stack:** Python 3, FastAPI, uvicorn, pydantic-settings, pytest, Markdown --- ## File Structure - `lsfx-mock-server/config/settings.py`: 新增 `RULE_HIT_MODE` 配置项,统一暴露规则命中模式。 - `lsfx-mock-server/main.py`: 新增普通启动命令行参数解析,并在启动前校验模式值。 - `lsfx-mock-server/dev.py`: 新增热重载启动入口,支持 `--reload --rule-hit-mode ...`。 - `lsfx-mock-server/services/file_service.py`: 为 `subset/all` 两种模式生成命中计划,并显式维护互斥组裁剪逻辑。 - `lsfx-mock-server/tests/test_file_service.py`: 锁定默认随机子集模式、`all` 模式全集逻辑和互斥组行为。 - `lsfx-mock-server/tests/test_startup.py`: 锁定命令行参数解析、非法参数报错和热重载启动参数透传。 - `lsfx-mock-server/README.md`: 更新普通启动、热重载启动与“全部兼容规则命中”的准确说明。 - `docs/reports/implementation/2026-03-22-lsfx-rule-hit-mode-backend-record.md`: 记录本次后端实施范围、命中模式语义和落地结果。 - `docs/tests/records/2026-03-22-lsfx-rule-hit-mode-backend-verification.md`: 记录测试命令、启动验证和进程清理结果。 ### Task 1: 接入命令行启动参数并统一规则命中模式配置 **Files:** - Modify: `lsfx-mock-server/config/settings.py` - Modify: `lsfx-mock-server/main.py` - Create: `lsfx-mock-server/dev.py` - Create: `lsfx-mock-server/tests/test_startup.py` - Reference: `docs/superpowers/specs/2026-03-22-lsfx-rule-hit-mode-design.md` - [ ] **Step 1: Write the failing test** 先在 `lsfx-mock-server/tests/test_startup.py` 中补三条失败用例,锁定启动参数语义: ```python import pytest from main import parse_args as parse_main_args from dev import parse_args as parse_dev_args def test_main_parse_args_should_default_to_subset(): args = parse_main_args([]) assert args.rule_hit_mode == "subset" def test_main_parse_args_should_accept_all_mode(): args = parse_main_args(["--rule-hit-mode", "all"]) assert args.rule_hit_mode == "all" def test_dev_parse_args_should_reject_invalid_mode(): with pytest.raises(SystemExit): parse_dev_args(["--rule-hit-mode", "invalid"]) ``` - [ ] **Step 2: Run test to verify it fails** Run: ```bash cd lsfx-mock-server python3 -m pytest tests/test_startup.py -v ``` Expected: - `FAIL` - 原因是 `main.py` 与热重载入口尚未提供可测试的参数解析函数 - [ ] **Step 3: Write minimal implementation** 按最小路径实现: 1. 在 `config/settings.py` 中新增默认配置: ```python RULE_HIT_MODE: str = "subset" ``` 2. 在 `main.py` 中新增参数解析函数,只允许 `subset|all`: ```python def parse_args(argv=None): parser = argparse.ArgumentParser() parser.add_argument("--rule-hit-mode", choices=["subset", "all"], default="subset") return parser.parse_args(argv) ``` 3. 在 `main.py` 启动前,将 `rule_hit_mode` 写入环境变量,再初始化/读取 `settings`。 4. 新增 `dev.py`,复用同一套参数解析,支持: ```bash python dev.py --reload --rule-hit-mode all ``` 5. `dev.py` 内部调用 `uvicorn.run("main:app", reload=True, ...)` 或等价方式,不再要求用户直接运行裸 `uvicorn main:app --reload ...`。 - [ ] **Step 4: Run test to verify it passes** Run: ```bash cd lsfx-mock-server python3 -m pytest tests/test_startup.py -v ``` Expected: - `PASS` - 默认模式为 `subset` - `all` 模式可被普通启动与热重载入口正确解析 - [ ] **Step 5: Commit** ```bash git add lsfx-mock-server/config/settings.py lsfx-mock-server/main.py lsfx-mock-server/dev.py lsfx-mock-server/tests/test_startup.py git commit -m "补充Mock规则命中模式启动参数" ``` ### Task 2: 在 FileService 中实现全部兼容规则命中计划 **Files:** - Modify: `lsfx-mock-server/services/file_service.py` - Modify: `lsfx-mock-server/tests/test_file_service.py` - Reference: `lsfx-mock-server/services/statement_rule_samples.py` - Reference: `docs/superpowers/specs/2026-03-22-lsfx-rule-hit-mode-design.md` - [ ] **Step 1: Write the failing test** 在 `lsfx-mock-server/tests/test_file_service.py` 中先补失败用例,锁定 `all` 模式语义: ```python def test_build_rule_hit_plan_should_return_all_compatible_rules_in_all_mode(monkeypatch): monkeypatch.setattr("services.file_service.settings.RULE_HIT_MODE", "all") service = FileService(staff_identity_repository=FakeStaffIdentityRepository()) plan = service._build_rule_hit_plan(10001) assert plan["large_transaction_hit_rules"] == LARGE_TRANSACTION_RULE_CODES assert plan["phase1_hit_rules"] == PHASE1_RULE_CODES assert plan["phase2_statement_hit_rules"] == PHASE2_STATEMENT_RULE_CODES assert plan["phase2_baseline_hit_rules"] == PHASE2_BASELINE_RULE_CODES def test_build_rule_hit_plan_should_keep_subset_mode_as_default(): service = FileService(staff_identity_repository=FakeStaffIdentityRepository()) plan1 = service._build_rule_hit_plan(10001) plan2 = service._build_rule_hit_plan(10001) assert plan1 == plan2 assert 2 <= len(plan1["large_transaction_hit_rules"]) <= 4 def test_build_rule_hit_plan_should_drop_conflicting_rules_from_all_mode(monkeypatch): monkeypatch.setattr("services.file_service.settings.RULE_HIT_MODE", "all") monkeypatch.setattr( "services.file_service.RULE_CONFLICT_GROUPS", [["SALARY_QUICK_TRANSFER", "SALARY_UNUSED"]], ) service = FileService(staff_identity_repository=FakeStaffIdentityRepository()) plan = service._build_rule_hit_plan(10001) assert not ( "SALARY_QUICK_TRANSFER" in plan["phase2_statement_hit_rules"] and "SALARY_UNUSED" in plan["phase2_statement_hit_rules"] ) ``` - [ ] **Step 2: Run test to verify it fails** Run: ```bash cd lsfx-mock-server python3 -m pytest tests/test_file_service.py -k "rule_hit_plan" -v ``` Expected: - `FAIL` - 原因是当前 `_build_rule_hit_plan()` 只有稳定随机子集逻辑,尚无模式切换和互斥裁剪 - [ ] **Step 3: Write minimal implementation** 在 `lsfx-mock-server/services/file_service.py` 中按职责做最小拆分: 1. 保留现有四类规则池常量。 2. 新增互斥组常量,第一版允许为空列表: ```python RULE_CONFLICT_GROUPS = [] ``` 3. 新增模式编排辅助函数: ```python def _build_subset_rule_hit_plan(self, log_id: int) -> dict: ... def _build_all_compatible_rule_hit_plan(self) -> dict: ... def _apply_conflict_groups(self, rule_plan: dict) -> dict: ... ``` 4. `_build_rule_hit_plan()` 只负责分发: ```python if settings.RULE_HIT_MODE == "all": return self._apply_conflict_groups(self._build_all_compatible_rule_hit_plan()) return self._build_subset_rule_hit_plan(log_id) ``` 5. 不修改 `FileRecord` 字段结构和后续消费链路,只改变计划生成方式。 - [ ] **Step 4: Run test to verify it passes** Run: ```bash cd lsfx-mock-server python3 -m pytest tests/test_file_service.py -k "rule_hit_plan" -v ``` Expected: - `PASS` - 默认仍为随机子集 - `all` 模式返回全部兼容规则 - 若未来配置互斥组,同组规则不会同时出现在结果里 - [ ] **Step 5: Commit** ```bash git add lsfx-mock-server/services/file_service.py lsfx-mock-server/tests/test_file_service.py git commit -m "补充Mock全部兼容规则命中计划" ``` ### Task 3: 更新文档并完成后端验证记录 **Files:** - Modify: `lsfx-mock-server/README.md` - Create: `docs/reports/implementation/2026-03-22-lsfx-rule-hit-mode-backend-record.md` - Create: `docs/tests/records/2026-03-22-lsfx-rule-hit-mode-backend-verification.md` - [ ] **Step 1: Update README with accurate startup instructions** 更新 `lsfx-mock-server/README.md`: - 普通启动示例改为: ```bash python main.py --rule-hit-mode subset python main.py --rule-hit-mode all ``` - 热重载示例改为: ```bash python dev.py --reload --rule-hit-mode subset python dev.py --reload --rule-hit-mode all ``` - 文案统一使用“全部兼容规则命中”,不使用“全部规则命中”。 - [ ] **Step 2: Run targeted verification** Run: ```bash cd lsfx-mock-server python3 -m pytest tests/test_startup.py tests/test_file_service.py -k "rule_hit_plan or parse_args" -v ``` Expected: - `PASS` - 启动参数与规则计划两条主链路均被锁定 - [ ] **Step 3: Run startup smoke tests and stop processes** 分别执行并记录: ```bash cd lsfx-mock-server python3 main.py --rule-hit-mode all > /tmp/lsfx_main.log 2>&1 & echo $! > /tmp/lsfx_main.pid sleep 3 kill "$(cat /tmp/lsfx_main.pid)" rm -f /tmp/lsfx_main.pid python3 dev.py --reload --rule-hit-mode all > /tmp/lsfx_dev.log 2>&1 & echo $! > /tmp/lsfx_dev.pid sleep 5 kill "$(cat /tmp/lsfx_dev.pid)" rm -f /tmp/lsfx_dev.pid ``` Expected: - 两种启动方式均成功拉起 - 结束验证后无残留进程 - [ ] **Step 4: Write implementation and verification records** 在实施记录中写清: - 默认模式保持不变 - `all` 的准确语义是“全部兼容规则命中” - 当前互斥组为空或具体清单 - 热重载改为项目脚本入口 在验证记录中写清: - 测试命令及结果 - 启动验证命令及结果 - 进程清理动作 - [ ] **Step 5: Commit** ```bash git add lsfx-mock-server/README.md docs/reports/implementation/2026-03-22-lsfx-rule-hit-mode-backend-record.md docs/tests/records/2026-03-22-lsfx-rule-hit-mode-backend-verification.md git commit -m "补充Mock命中模式后端实施与验证记录" ```