Skip to content

Commit 8d474b4

Browse files
committed
fix CodeQL alert
1 parent ce2181b commit 8d474b4

4 files changed

Lines changed: 39 additions & 46 deletions

File tree

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,11 @@ A complete reasoning session typically answers the following questions:
4444
* **Strategy Effectiveness?** Under what circumstances is an "open ecosystem" superior to "vertical integration"?
4545
* **Endgame Form?** Does it move towards monopoly, oligarchic balance, or fragmented coexistence?
4646

47+
---
48+
4749
## 🚀 Quick Start
4850

49-
### Installation
51+
### 🏗️ Installation
5052

5153
Environment requirements: Python 3.12+ with `pip` package manager.
5254

@@ -57,7 +59,7 @@ pip install --upgrade pip setuptools wheel
5759
pip install -e .
5860
```
5961

60-
### View Example
62+
### 🌰 View Example
6163

6264
If you want to quickly see Omen in action, a visualized sample case and its results are available in the `sample` directory. Run:
6365

@@ -67,7 +69,7 @@ streamlit run sample/app/scenario_planning.py
6769

6870
Then open `http://localhost:8501` in your browser to explore the full strategic reasoning flow.
6971

70-
### Run Built-in Case
72+
### 🎵 Run Built-in Case
7173

7274
If you want to run a complete end-to-end workflow, we have prepared a built-in case simulating SAP's acquisition of Reltio in March 2026. The case document is `cases/sap_reltio_acquisition.md`, and it can be run end-to-end with the following commands:
7375

README.zh.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,11 @@ Omen **不预测**单一未来,它是**为复杂性而生**的推演引擎。
4545
* **策略有效性?** 在何种情境下,“开放生态”优于“垂直整合”?
4646
* **终局形态?** 走向垄断、寡头平衡还是碎片化共存?
4747

48+
---
49+
4850
## 🚀 快速开始
4951

50-
### 安装
52+
### 🏗️ 安装
5153

5254
运行环境要求:Python 3.12+,并使用 `pip` 包管理器。
5355

@@ -58,7 +60,7 @@ pip install --upgrade pip setuptools wheel
5860
pip install -e .
5961
```
6062

61-
### 查看示例
63+
### 🌰 看个例子
6264

6365
如果你希望快速查看 Omen 的运行效果,`sample` 目录中提供了可视化案例及其结果。运行:
6466

@@ -68,7 +70,7 @@ streamlit run sample/app/scenario_planning.py
6870

6971
然后在浏览器中打开 `http://localhost:8501`,即可查看完整的战略推演流程。
7072

71-
### 运行示例
73+
### 🎵 亲自运行
7274

7375
如果你希望亲自运行一遍完整的流程,请使用我们准备的内置案例,用于模拟 2026 年 3 月 SAP 收购 Reltio 的情境。案例文档位于 `cases/sap_reltio_acquisition.md`,可以通过以下步骤端到端运行。
7476

app/scenario_planning.py

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,21 @@ def _normalize_pack_id(value: Any) -> str:
2929

3030

3131
def _resolve_safe_root(raw_value: str, default_rel: str) -> Path:
32-
workspace_real = os.path.realpath(str(WORKSPACE_ROOT))
33-
default_path = Path(os.path.realpath(str(WORKSPACE_ROOT / default_rel)))
32+
workspace_base = os.path.normpath(str(WORKSPACE_ROOT))
33+
default_path = Path(os.path.normpath(os.path.join(workspace_base, default_rel)))
34+
3435
raw = str(raw_value or "").strip()
3536
if not raw:
3637
return default_path
3738

38-
candidate = Path(raw)
39-
if not candidate.is_absolute():
40-
candidate = WORKSPACE_ROOT / candidate
41-
candidate_real = os.path.realpath(str(candidate))
39+
if not os.path.isabs(raw):
40+
fullpath = os.path.normpath(os.path.join(workspace_base, raw))
41+
else:
42+
fullpath = os.path.normpath(raw)
4243

43-
if os.path.commonpath([workspace_real, candidate_real]) != workspace_real:
44+
if not fullpath.startswith(workspace_base):
4445
return default_path
45-
return Path(candidate_real)
46+
return Path(fullpath)
4647

4748

4849
def _render_json(path: str, payload: dict[str, Any] | None) -> None:
@@ -55,33 +56,27 @@ def _render_json(path: str, payload: dict[str, Any] | None) -> None:
5556

5657
def _read_json_file(*, base_dir: Path, pack_id: str, filename: str) -> dict[str, Any] | None:
5758
try:
58-
workspace_real = os.path.realpath(str(WORKSPACE_ROOT))
59-
base_real = os.path.realpath(str(base_dir))
60-
if os.path.commonpath([workspace_real, base_real]) != workspace_real:
59+
workspace_base = os.path.normpath(str(WORKSPACE_ROOT))
60+
base_path = os.path.normpath(str(base_dir))
61+
if not base_path.startswith(workspace_base):
6162
return None
6263

6364
safe_pack_id = _normalize_pack_id(pack_id)
6465
if not safe_pack_id:
6566
return None
6667

67-
target_real = os.path.realpath(str(Path(base_real) / safe_pack_id / filename))
68-
except Exception:
69-
return None
70-
71-
if os.path.commonpath([workspace_real, target_real]) != workspace_real:
72-
return None
73-
if os.path.commonpath([base_real, target_real]) != base_real:
74-
return None
68+
fullpath = os.path.normpath(os.path.join(base_path, safe_pack_id, filename))
69+
if not fullpath.startswith(base_path):
70+
return None
7571

76-
resolved_path = Path(target_real)
77-
if not resolved_path.exists() or not resolved_path.is_file():
78-
return None
72+
resolved_path = Path(fullpath)
73+
if not resolved_path.exists() or not resolved_path.is_file():
74+
return None
7975

80-
try:
8176
payload = json.loads(resolved_path.read_text(encoding="utf-8"))
77+
return payload if isinstance(payload, dict) else None
8278
except Exception:
8379
return None
84-
return payload if isinstance(payload, dict) else None
8580

8681

8782
def _load_scenario_slot_labels() -> dict[str, str]:

sample/app/scenario_planning.py

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,33 +37,27 @@ def _render_json(path: str, payload: dict[str, Any] | None) -> None:
3737

3838
def _read_json_file(*, base_dir: Path, pack_id: str, filename: str) -> dict[str, Any] | None:
3939
try:
40-
workspace_real = os.path.realpath(str(WORKSPACE_ROOT))
41-
base_real = os.path.realpath(str(base_dir))
42-
if os.path.commonpath([workspace_real, base_real]) != workspace_real:
40+
workspace_base = os.path.normpath(str(WORKSPACE_ROOT))
41+
base_path = os.path.normpath(str(base_dir))
42+
if not base_path.startswith(workspace_base):
4343
return None
4444

4545
safe_pack_id = _normalize_pack_id(pack_id)
4646
if not safe_pack_id:
4747
return None
4848

49-
target_real = os.path.realpath(str(Path(base_real) / safe_pack_id / filename))
50-
except Exception:
51-
return None
52-
53-
if os.path.commonpath([workspace_real, target_real]) != workspace_real:
54-
return None
55-
if os.path.commonpath([base_real, target_real]) != base_real:
56-
return None
49+
fullpath = os.path.normpath(os.path.join(base_path, safe_pack_id, filename))
50+
if not fullpath.startswith(base_path):
51+
return None
5752

58-
resolved_path = Path(target_real)
59-
if not resolved_path.exists() or not resolved_path.is_file():
60-
return None
53+
resolved_path = Path(fullpath)
54+
if not resolved_path.exists() or not resolved_path.is_file():
55+
return None
6156

62-
try:
6357
payload = json.loads(resolved_path.read_text(encoding="utf-8"))
58+
return payload if isinstance(payload, dict) else None
6459
except Exception:
6560
return None
66-
return payload if isinstance(payload, dict) else None
6761

6862

6963
def _load_sample_actor_payloads(pack_id: str) -> dict[str, Any]:

0 commit comments

Comments
 (0)