10 KiB
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 中补三条失败用例,锁定启动参数语义:
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:
cd lsfx-mock-server
python3 -m pytest tests/test_startup.py -v
Expected:
-
FAIL -
原因是
main.py与热重载入口尚未提供可测试的参数解析函数 -
Step 3: Write minimal implementation
按最小路径实现:
- 在
config/settings.py中新增默认配置:
RULE_HIT_MODE: str = "subset"
- 在
main.py中新增参数解析函数,只允许subset|all:
def parse_args(argv=None):
parser = argparse.ArgumentParser()
parser.add_argument("--rule-hit-mode", choices=["subset", "all"], default="subset")
return parser.parse_args(argv)
- 在
main.py启动前,将rule_hit_mode写入环境变量,再初始化/读取settings。 - 新增
dev.py,复用同一套参数解析,支持:
python dev.py --reload --rule-hit-mode all
dev.py内部调用uvicorn.run("main:app", reload=True, ...)或等价方式,不再要求用户直接运行裸uvicorn main:app --reload ...。
- Step 4: Run test to verify it passes
Run:
cd lsfx-mock-server
python3 -m pytest tests/test_startup.py -v
Expected:
-
PASS -
默认模式为
subset -
all模式可被普通启动与热重载入口正确解析 -
Step 5: Commit
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 模式语义:
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:
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 中按职责做最小拆分:
- 保留现有四类规则池常量。
- 新增互斥组常量,第一版允许为空列表:
RULE_CONFLICT_GROUPS = []
- 新增模式编排辅助函数:
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:
...
_build_rule_hit_plan()只负责分发:
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)
- 不修改
FileRecord字段结构和后续消费链路,只改变计划生成方式。
- Step 4: Run test to verify it passes
Run:
cd lsfx-mock-server
python3 -m pytest tests/test_file_service.py -k "rule_hit_plan" -v
Expected:
-
PASS -
默认仍为随机子集
-
all模式返回全部兼容规则 -
若未来配置互斥组,同组规则不会同时出现在结果里
-
Step 5: Commit
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:
- 普通启动示例改为:
python main.py --rule-hit-mode subset
python main.py --rule-hit-mode all
- 热重载示例改为:
python dev.py --reload --rule-hit-mode subset
python dev.py --reload --rule-hit-mode all
-
文案统一使用“全部兼容规则命中”,不使用“全部规则命中”。
-
Step 2: Run targeted verification
Run:
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
分别执行并记录:
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
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命中模式后端实施与验证记录"