Land QA fixes and repository hygiene guardrails

This commit is contained in:
732642856
2026-06-29 03:25:03 +08:00
parent 4bd1e6db70
commit 25000647e7
8 changed files with 100 additions and 2 deletions
+3
View File
@@ -6,6 +6,9 @@ __pycache__/
.agents/ .agents/
venv_vedastro/ venv_vedastro/
scratch/local/ scratch/local/
scratch/test_*.json
scratch/test_*.txt
test_hooks.json
hermes_memory.db/ hermes_memory.db/
*.egg-info/ *.egg-info/
dist/ dist/
+4
View File
@@ -161,3 +161,7 @@
- Round 7 后续审计发现:如果未来人工把 oracle JSON 某条 case 升级为 `external_verified`,旧队列生成器会重新生成 draft evidence packet,导致“已填外部真值仍过不了 validator”。已修为保留 `evidence_packet.status/metadata`,并用 `target_fields` 固定目标字段集合。 - Round 7 后续审计发现:如果未来人工把 oracle JSON 某条 case 升级为 `external_verified`,旧队列生成器会重新生成 draft evidence packet,导致“已填外部真值仍过不了 validator”。已修为保留 `evidence_packet.status/metadata`,并用 `target_fields` 固定目标字段集合。
- 对标差距结论:相对 VedAstro/PyJHora/JHora,当前最实质缺口不是基础 D1/D9,而是 Dasha/Shadbala 外部真值样本库、合婚/Koota/Panchanga 的 API/产品深度、以及普通用户一键使用/校准状态可视化。PyJHora 因 AGPL 只能黑盒参照,JHora 因闭源只能截图级人工采集。 - 对标差距结论:相对 VedAstro/PyJHora/JHora,当前最实质缺口不是基础 D1/D9,而是 Dasha/Shadbala 外部真值样本库、合婚/Koota/Panchanga 的 API/产品深度、以及普通用户一键使用/校准状态可视化。PyJHora 因 AGPL 只能黑盒参照,JHora 因闭源只能截图级人工采集。
- 2026-06-26 Round 28/29 接力结论:Round 28 的 30 份研究报告已回到主仓待归档区,覆盖全球开源排名、PyJHora/JHora 广度差距、MIT 可复制资产、Dasha/Panchanga/Muhurta/Synastry/Shadbala/Jaimini/KP/Varga/Yoga 深度路线、skill 同步缺口、真新增技法最小集与 Round29 Top100;同时新增 `docs/research/antigravity_sidecar_work_order_round29_2026_06_26.md`,将副手任务继续加压到 skill 全量补齐差距、API/CLI/前端隐藏能力、整机碎片复用第二轮、云端同步白名单、外部 oracle 精度闭环与 Round30 Top120。 - 2026-06-26 Round 28/29 接力结论:Round 28 的 30 份研究报告已回到主仓待归档区,覆盖全球开源排名、PyJHora/JHora 广度差距、MIT 可复制资产、Dasha/Panchanga/Muhurta/Synastry/Shadbala/Jaimini/KP/Varga/Yoga 深度路线、skill 同步缺口、真新增技法最小集与 Round29 Top100;同时新增 `docs/research/antigravity_sidecar_work_order_round29_2026_06_26.md`,将副手任务继续加压到 skill 全量补齐差距、API/CLI/前端隐藏能力、整机碎片复用第二轮、云端同步白名单、外部 oracle 精度闭环与 Round30 Top120。
- 2026-06-28 真实用户全功能 QA:使用 `REDACTED_DATE REDACTED_TIME`、河北REDACTED_PLACEREDACTED_PLACE矿区近似坐标 `36.4467,114.2` 跑完 CLI/API/前端点击/质量门矩阵。能力注册表 89 项有效、碎片审计 37 CLI + 41 API 无未注册高价值候选、前端 `--mode all` 浏览器点击通过、quick quality gate 通过;正式报告见 `docs/research/sample_user_full_function_qa_REDACTED_YEAR_redacted_place_2026_06_28.md`
- 本轮 QA 真 bug`jyotish_engine.py muhurta` CLI 因 Sun/Moon tuple 进入 `calc_tithi` 崩溃;`varga-full --divisions ... D81/D108/D144` 仍走旧 `scripts/varga.py` 而失败,尽管 `--custom 81` 可算;`/api/remedies` 对数值型 Shadbala 简写会 500,应归一化或返回 400。
- 本轮 QA 边界结论:`/api/technique_example` 用目录官方 example payload 可 200,普通出生资料直打 400 是合同误用而非后端坏;`db-stats` 返回数据库不存在,说明入口可用但本机 celebrity/validation DB 数据源缺席;外部 JHora/PyJHora/VedAstro oracle 精度仍未因此闭环。
- VedAstro 强制雷达边界:官方 Events Builder 暴露 `SearchEvents / GetEventTiming / ListEventTypes` 三个事件端点、400+ 预定义事件和 `Scan precision (hours)`API/Python surface 继续按 600+/596+ 计算节点理解。本项目不硬复刻 596 个函数,而是把 VedAstro range scan 作为 `career/relationship/finance` strict workflow 的必需外部高频 timing radar;缺失时进入 `vedastro_range_scan_missing` 和 Technique Audit blocked 行,不能再静默跳过。
+20
View File
@@ -423,3 +423,23 @@
- `oracle_functional_benefics.py` 新增 CLI JSON 合同测试;`python3 scripts/audit_fragments.py --strict` 显示 candidate_count 从 3 降到 0。 - `oracle_functional_benefics.py` 新增 CLI JSON 合同测试;`python3 scripts/audit_fragments.py --strict` 显示 candidate_count 从 3 降到 0。
- Functional Benefic/Malefic 的 `Technique Audit Table` 与 real-reading checklist 现在显式要求/输出 `functional_neutrals``yogakarakas` - Functional Benefic/Malefic 的 `Technique Audit Table` 与 real-reading checklist 现在显式要求/输出 `functional_neutrals``yogakarakas`
- 合婚 strict bridge 修复 `additional_kutas.BadConstellations` 的 nested dict 形态,并把 mitigation exceptions 折叠成 `exception_mitigated_match`,防止已有 Ashtakoot 细节资产在 relationship adjudicator 中被吞掉。 - 合婚 strict bridge 修复 `additional_kutas.BadConstellations` 的 nested dict 形态,并把 mitigation exceptions 折叠成 `exception_mitigated_match`,防止已有 Ashtakoot 细节资产在 relationship adjudicator 中被吞掉。
## 2026-06-28T20:05:00+08:00 - REDACTED_YEAR REDACTED_PLACE真实用户全功能 QA
- 按用户要求以 `REDACTED_DATE REDACTED_TIME`、中国河北REDACTED_PLACEREDACTED_PLACE矿区近似坐标 `lat=36.4467 lon=114.2 tz=8` 跑真实用户全功能验收;scratch 产物放在 `scratch/local/sample_user_qa_2026_06_28/`
- CLI 矩阵覆盖 30 条出生盘/事件/合盘/问事/年运/分盘命令,28 条通过;失败为 `varga-full --divisions` 高分盘 D81/D108/D144 路由旧实现、`muhurta` CLI tuple longitude 崩溃。
- API 矩阵覆盖 42 个请求,40 个通过;`/api/remedies` 对数值型 Shadbala 简写返回 500,官方 catalog payload 可通过;`/api/technique_example` 用 catalog example payload 通过,普通出生资料直打 400 归类为合同边界。
- 前端真实浏览器 `python3 tests/run_frontend_click_smoke.py --mode all --timeout 420` 通过,覆盖 core/mobile/offline/pdf/workspace/mobile-trust/import-files`npm run build` 通过。
- 工程守门通过:`python3 scripts/audit_capabilities.py --mode validate` 有效;`python3 scripts/audit_fragments.py --strict` 有效且 candidate_count=0`python3 scripts/run_quality_gate.py --profile quick --skip-frontend-runtime` 通过,配置内 283 项 pytest 通过。
- 新增正式报告 `docs/research/sample_user_full_function_qa_REDACTED_YEAR_redacted_place_2026_06_28.md`,下一步优先修复 `muhurta` CLI、`varga-full --divisions` 高分盘合同、`/api/remedies` 输入硬化,并单独处理当前 dirty worktree/scratch 残留。
## 2026-06-28T21:25:00+08:00 - VedAstro 596+/Events 高频雷达强制合同
- 用户明确要求必须使用外部 VedAstro 596+ 高频流年 API;本轮不把它误解成要本地硬复刻 596 个函数,而是把 VedAstro 作为外部高频 timing radar 接入 strict workflow 边界。
- 复核官方公开面:`APIBuilder.html` 对应通用 calculator surface`EventsChartAPIBuilder.html` 元数据写明 `SearchEvents / GetEventTiming / ListEventTypes`、400+ pre-defined events,并有 `Scan precision (hours)`PyPI `vedastro` 当前观测版本为 `1.23.25`
- `scripts/vedastro_service_adapter.py --print-schema` 新增 `vedastro_calculation_coverage`,记录 `596+` Python calculations、`600+` API Builder calculators、`400+` Events Builder events、三事件方法,以及 `high_frequency_life_event_radar` 用途。
- VedAstro range-scan preview 现在显式包含 `vedastro_event_method = SearchEvents`,并继续通过 `VEDASTRO_API_ENDPOINT``VEDASTRO_ENABLE_NETWORK` 做外部服务边界控制。
- `mcp_server.py``career / relationship / finance` 的 strict workflow 现在把 `external_activation` 视为必需 VedAstro 外部雷达槽;缺失时输出 `missing_required_external_radar``vedastro_range_scan_missing``Technique Audit` blocked 行;有事件时输出 `used` 行和 event_count。
- 守住边界:VedAstro 事件证据不直接替代本地双重大运、分盘、Shadbala/Ashtakavarga/Jaimini/Functional role,也不直接设置 `dominant_label / payout_label`;缺本地 promise 时仍受原评分上限约束。
- 新增审计文档 `docs/research/vedastro_required_high_frequency_radar_contract_2026_06_28.md`
- 验证:`python3 -m pytest tests/test_vedastro_service_adapter_executor.py tests/test_vedastro_external_technique_evidence.py tests/test_vedastro_parity_matrix.py tests/test_vedastro_adapter_candidate_guard.py -q` 通过;`python3 -m pytest tests/test_mcp_strict_workflow_finance.py tests/test_mcp_strict_workflow_relationship.py tests/test_mcp_strict_workflow_career.py tests/test_life_event_graph_v1.py -q` 通过。
+6 -1
View File
@@ -28,13 +28,18 @@ def _weekday_to_vara(py_weekday: int) -> int:
def _get_sun_moon_lons(year: int, month: int, day: int, def _get_sun_moon_lons(year: int, month: int, day: int,
hour: int = 12, ayanamsa_name: str = 'lahiri') -> tuple: hour: int = 12, ayanamsa_name: str = 'lahiri') -> tuple:
"""获取太阳/月亮恒星黄经。优先 swisseph,退化为近似算法。""" """获取太阳/月亮恒星黄经。优先 swisseph,退化为近似算法。"""
def _primary_longitude(value):
if isinstance(value, (list, tuple)):
return float(value[0])
return float(value)
try: try:
import swisseph as swe import swisseph as swe
jd_ut = swe.julday(year, month, day, hour) jd_ut = swe.julday(year, month, day, hour)
flags = sidereal_flags(swe, ayanamsa_name) flags = sidereal_flags(swe, ayanamsa_name)
sun_res = swe.calc_ut(jd_ut, swe.SUN, flags) sun_res = swe.calc_ut(jd_ut, swe.SUN, flags)
moon_res = swe.calc_ut(jd_ut, swe.MOON, flags) moon_res = swe.calc_ut(jd_ut, swe.MOON, flags)
return sun_res[0], moon_res[0], True return _primary_longitude(sun_res[0]), _primary_longitude(moon_res[0]), True
except Exception: except Exception:
pass pass
# 近似算法 # 近似算法
+17
View File
@@ -2962,6 +2962,23 @@ def cmd_varga_full(args):
result[pn] = calc.calc_varga_with_variant(lon, divisions[0], variant) result[pn] = calc.calc_varga_with_variant(lon, divisions[0], variant)
return result return result
try:
sys.path.insert(0, SCRIPT_DIR)
from divisional_charts_extended import DivisionalChartsCalculator, VargaType
extended_available = {varga.division: varga for varga in VargaType}
if any(division not in {2, 3, 4, 7, 9, 10, 12, 16, 20, 24, 27, 30, 40, 45, 60} for division in (divisions or [])):
calc = DivisionalChartsCalculator()
selected = [extended_available[division] for division in divisions]
result = {}
for varga in selected:
key = f'D{varga.division}_{varga.varga_name}'
result[key] = calc._calculate_single_varga(varga, planet_lons, asc_deg)
return result
except KeyError as e:
return {"error": f"不支持的D{e.args[0]}。请使用 --custom N 计算任意D-N分盘。"}
except ImportError:
pass
return calc_all_vargas(planet_lons, asc_deg, divisions) return calc_all_vargas(planet_lons, asc_deg, divisions)
+6 -1
View File
@@ -104,7 +104,12 @@ def recommend_remedies(shadbala_results: Dict, planet_dignities: Dict = None,
evidence_chain = [] evidence_chain = []
for planet, data in shadbala_results.items(): for planet, data in shadbala_results.items():
rupas = data.get('total_rupas', data.get('rupas', 1.0)) if isinstance(data, (int, float)) and not isinstance(data, bool):
rupas = float(data)
elif isinstance(data, dict):
rupas = data.get('total_rupas', data.get('rupas', 1.0))
else:
rupas = 1.0
if rupas < STRENGTH_THRESHOLDS['weak']: if rupas < STRENGTH_THRESHOLDS['weak']:
weak_planets.append(planet) weak_planets.append(planet)
evidence_chain.append({ evidence_chain.append({
+13
View File
@@ -368,6 +368,19 @@ def test_remedies_accepts_api_rupas_shape() -> None:
assert result['recommendations']['mantras'] assert result['recommendations']['mantras']
def test_remedies_endpoint_accepts_numeric_shadbala_shorthand() -> None:
handler = _handler()
result = handler._compute_remedies({
'shadbala': {'Sun': 0.42, 'Moon': 0.68},
'dasha_lord': 'Saturn',
'doshas': ['Mangal Dosha'],
})
assert result['weak_planets'] == ['Sun']
assert 'Moon' in result['moderate_planets']
assert any(item['source'] == 'shadbala' and item['planet'] == 'Sun' for item in result['evidence_chain'])
def test_import_chart_accepts_plain_text() -> None: def test_import_chart_accepts_plain_text() -> None:
handler = _handler() handler = _handler()
result = handler._import_chart_text({ result = handler._import_chart_text({
+31
View File
@@ -398,6 +398,37 @@ def test_varga_cli_outputs_d9_and_d10() -> None:
assert "Moon" in charts["D9_Navamsa"] assert "Moon" in charts["D9_Navamsa"]
def test_varga_full_cli_divisions_supports_high_vargas() -> None:
result = run_engine(
"varga-full",
*BASE_BIRTH_ARGS,
"--divisions",
"D9,D60,D81,D108,D144",
)
assert "D81_Navamsa-Navamsa" in result
assert "D108_Dwadasamsa-Navamsa" in result
assert "D144_Dwadasamsa-Dwadasamsa" in result
assert result["D144_Dwadasamsa-Dwadasamsa"]["planets"]["Moon"]["house"] in range(1, 13)
def test_muhurta_cli_scan_days_outputs_panchanga_without_tuple_crash() -> None:
output = run_engine_text(
"muhurta",
"--date",
"2026-06-28",
"--activity",
"business",
"--scan-days",
"2",
)
assert "Muhurta" in output
assert "Panchanga" in output
assert "2026-06-28" in output
assert "unsupported operand type" not in output
def test_ashtakavarga_cli_keeps_sav_invariant() -> None: def test_ashtakavarga_cli_keeps_sav_invariant() -> None:
result = run_engine("ashtakavarga", *BASE_BIRTH_ARGS) result = run_engine("ashtakavarga", *BASE_BIRTH_ARGS)
assert result["sav"]["total"] == 337 assert result["sav"]["total"] == 337