Metadata-Version: 2.4
Name: aps-kernel
Version: 1.33.0
Summary: Deterministic CP-SAT scheduling kernel, independent schedule validator, and headless CLI — APS standard edition
Author: APS Contributors
License: MIT
Project-URL: Homepage, https://aps.zhinengti.online
Project-URL: Documentation, https://github.com/123aiot/aps/tree/main/docs
Project-URL: Source, https://github.com/123aiot/aps
Project-URL: Changelog, https://github.com/123aiot/aps/blob/main/CHANGELOG.md
Keywords: aps,scheduling,production-planning,cpsat,ortools,finite-capacity,manufacturing,aps-kernel
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Manufacturing
Classifier: Intended Audience :: Science/Research
Classifier: Natural Language :: Chinese (Simplified)
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: License :: OSI Approved :: MIT License
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: ortools>=9.10
Requires-Dist: pyyaml>=6.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: ruff>=0.6; extra == "dev"
Requires-Dist: mypy>=1.10; extra == "dev"
Provides-Extra: byoe
Requires-Dist: byoe>=3.7; extra == "byoe"
Dynamic: license-file

# aps-kernel — Metis 谋序（APS 标准版）

> **运筹帷幄，谋定后动** —— 同衡·谋序·同枢，智造同频。
> One Truth. One Plan. One Rhythm.

可嵌入的**确定性**排产内核：CP-SAT 精确求解、**独立复核器**、
工序-资源适配数据模型、设备槽位与班次日历、ε-约束 trade-off、headless CLI。

> **标准版 vs 专业版**：本包只含可嵌入内核（无 UI / 无服务 / 无 LLM）。
> 甘特图前端、Web 控制台、AI 编排层、多租户 RLS、审批与 IM 通道
> 属专业版（Docker 镜像 + docker compose）。

🌐 官网：https://aps.zhinengti.online
家族：Nereus 同衡（数字孪生）· Metis 谋序（智能排产）· Hermes 同枢（物流调度）

---

## ⭐ 求解能力（横向基准，非自说自话）

在 **16 个标准 FJSP 实例**（ft/la/abz/orb/swv/ta/yn，来源 `job_shop_lib` MIT，
含**文献公认最优值**）上的实测：

| 实例 | 工单×机器 | SPT 基线 | 规则链 | **CP-SAT** | 文献最优 | vs 最优 |
|---|---|---|---|---|---|---|
| ft06 | 6×6 | 94 | 92 | **55** | 55 | **+0.0% OPTIMAL** |
| ft10 | 10×10 | 1530 | 1310 | **930** | 930 | **+0.0% OPTIMAL** |
| ft20 | 20×5 | 1513 | 1565 | **1165** | 1165 | **+0.0% OPTIMAL** |
| la01-05 | 10×5 | ~1000 | ~940 | **最优** | — | **+0.0% OPTIMAL** |
| abz5/6 | 10×10 | ~1700 | ~1600 | **1234/943** | 同 | **+0.0% OPTIMAL** |
| orb01 | 10×10 | 1489 | 1631 | 1082 | 1059 | +2.2% FEASIBLE |
| swv01/02 | 20×10 | ~2100 | ~2100 | 1495/1562 | 1407/1475 | +6% FEASIBLE |
| ta01/02 | 15×15 | ~2100 | ~2040 | 1233/1248 | 1231/1244 | +0.3% FEASIBLE |
| yn1 | 20×20 | 1547 | 1509 | 944 | 884 | +6.8% FEASIBLE |

**11/16 达到文献最优**，其余为大规模实例（20 秒预算不足，已如实标 gap）。
**全部 11/11 独立复核通过。**

```bash
python benchmarks/run_standard_bench.py --time-limit 30
```

---

## 当前状态

**v1.33.0** —— 参数校准建议(实绩回路第二步:compare→calibrate→人批准→采纳=人改数据)+ T6b CLI/会话工具(aps_compare/aps_calibrate,13 工具)+ GBK 控制台修复 + CI 分层与双模块变异门 85%。上一版 1.32.0:质量卫生批。1255 tests passed

| 模块 | 状态 | 关键能力 |
|---|---|---|
| 数据模型 P0 | ✅ | 工序-资源适配、**空适配 ≠ 全设备可用**、槽位 |
| 输入校验 P0 | ✅ | 三项 P0 准则 + 5 类检查 + **跨窗口工序预警**（`OP_WINDOW_TOO_SMALL`，1.19.0） |
| 规则引擎 P1 | ✅ | **7 条规则**（CR/EDD/SPT/WKWR/ATC/加权优先级/**FIFO**）+ 8 条链 |
| 日历与齐套 P2 | ✅ | 三日历求交、**班次×资源×位置**、工单级齐套布尔判定 |
| 换型规则链 P2 | ✅ | frePPLe 语义、**无匹配 = 硬约束禁止**、参数配置化、**非对称 A→B≠B→A**、矩阵格式 |
| CP-SAT 求解 P3 | ✅ | **字典序三级目标**、容量池用 `AddCumulative`、冻结窗口 |
| 独立复核器 P4 | ✅ | **13 项真检查**（含日历可行、模具互斥、技能资格、**依赖满足**、**技能池容量**、**换型成本**）、用输入重算不信任求解器 |
| Provenance P4 | ✅ | 快照 hash + 配置/源码/求解器版本 |
| CLI + 基准 P5 | ✅ | `solve` / `benchmark` / `explain` / `chains` / `health` / **`lotting`** |
| 冲突诊断 | ✅ | `aps explain` —— 最小冲突集 + 排不下原因 |
| ε-约束 trade-off | ✅ | 钉住交期预算，问 makespan 能压到多少 |
| **数据体检** | ✅ | `aps health` —— 四张底账逐项核对 + 可执行率估计 |
| **设备负载均衡旋钮** | ✅ | ε-约束第 3 个旋钮：钉住设备负荷不均衡度 |
| **工装模具约束** | ✅ | 跨设备 NoOverlap —— 冲压/注塑的头号约束，「机床等模具」不再是隐患 |
| **并行工序** | ✅ | 同 `seq` 的工序可同时执行（双人工位装配 / 多工位并行检测）|
| **序列相关换型** | ✅ | 换型**真实占用产能**（贪心+CP-SAT+复核器三方一致）；A→B 与 B→A 可不同 |
| **换型成本** | ✅ | `SetupRule.cost`（元/次）→ `Assignment.setup_cost`，result.csv/甘特图/求解证书三个出口（1.17.0）。⚠️ 只计真换型，固定准备不计；四层费率由用户自配 |
| **换型矩阵格式** | ✅ | 直接贴工厂的换型矩阵表（行业通用格式），支持非对称与「禁止该换型」|
| **拆批合批** | ✅ | 求解前预处理；工时按数量缩放；最小批量约束；合批守交期红线 |
| **人员技能资格** | ✅ | 工序声明技能 → 资源必须**持证**（1.6.0）。无证资源自动跳过；缺证时警告点名技能而非静默 |
| **工序依赖** | ✅ | `predecessors` + `min_lag_minutes`（1.7.0）：跨工单拓扑就绪门 + 并行组内分层 + 前道完工地板；pred 未排 ⟹ 约束不生效（与 CP-SAT presence 语义一致） |
| **固定准备时间** | ✅ | `setup_seconds`（1.7.0）：装夹/调机首件确认每单必付，占用区间 `[start−P, end]` 两求解器+复核器三方同口径 |
| **有效工时（能率/倍速）** | ✅ | `Resource.max_efficiency`（设备能率上限）× `OperationResource.efficiency`（产品实际倍速），取 `min` 后折算工时（1.11.0）。2 腔注塑机跑 1 穴产品**不会**凭空快一倍 |
| **设备保养窗口** | ✅ | `Resource.maintenance` + `calendar.maintenance_schedule(every_days=6, duration_days=1)`（1.15.0）。日历层挖洞，两求解器+复核器天然同口径。⚠️ 周期按自然日近似，非按累计加工量 |
| **计划员入口（标准版用起来）** | ✅ | `aps demo` 生成 CSV 模板 → Excel 填报 → `aps solve --gantt/--csv/--certificate/--validation-report`。全程不写代码（1.9.0）。⭐ `aps demo --tight-due` 紧交期变体 + 配套急单：`aps whatif 目录 --add whatif-urgent.json --freeze-before 1000` 一跑就能看到 pushed/flipped_late（默认模板交期偏宽，这两栏恒为空——1.29.0 补的演示盲区） |
| **插单影响仿真（What-If）** | ✅ | `aps whatif --add delta.json`：插一个急单，**谁被推后/谁从准时变拖期/makespan 增多少**。冻结已下达计划 + 重排 + 差分；冻结逐条核对（`frozen_honored`），CP-SAT 回退贪心时如实标注质量降级（1.20.0） |
| **可解释规则链推荐** | ✅ | `aps recommend 输入.json`：按实例特征（换型组覆盖/交期紧度/等级差/候选数）推荐规则链，**每条推荐带可核对理由**；特征不足降级 default 标 weak，**不硬凑**；推荐不排他——附 benchmark 对比命令（1.30.0，策略回路第一步） |
| **计划执行风险（概率交期）** | ✅ | `aps risk 输入.json --plan plan.json`：时长 PERT-Beta 矩匹配采样 + 按计划顺序前向传播 ⟹ makespan 与各工单完工 P50/P80/P95、**每张单按期概率**、敏感性 TOP（哪道工序波动最伤交期）。口径诚实：计划固定、时长波动，非重新优化；同 seed 必同结果（1.30.0） |
| **审批账本（HITL）** | ✅ | `ApprovalLedger`（追加写 JSONL/SQLite）+ `ApprovalGate`：commit/方案切换/undo 等改变基线的动作过门，未批准 ⟹ 结构化拒绝 `APPROVAL_REQUIRED`；**AI 工具面刻意没有 approve**（AI 可提议可查看，不能裁决自己）。账本管决定不管执行（诚实边界写死）（1.31.0） |
| **求解参数/链草稿推荐** | ✅ | `recommend_solver_options`（特征⟹时间预算，出处式推论非新基准）；`validate_chain_draft`（LLM 写草稿、内核校验、人审入库 —— P2-6 纪律进校验） |
| **MS Project 导入** | ✅ | `aps import-mspdi 计划.xml`：只读 MSPDI（Project 另存为 XML）⟹ ScheduleInput + 逐条映射报告（摘要跳过/里程碑零工时/SS 等类型点名跳过/未分配落 UNASSIGNED 告警/日历不搬）。导入产物可排可复核（1.31.0） |
| **AI 会话方案管理** | ✅ | `ApsSession.commit/discard/undo/save_scheme/load_scheme`：「就按插了 J-7 的方案继续」可执行；commit 落库并**作废旧基线**（必须重解）；方案 A/B 对比；工具 `aps_apply_whatif`/`aps_scheme` 带结构化拒绝码（1.30.0） |
| **滚动重排编排（专业版）** | ✅ | `POST /api/v1/reschedule/rolling`：到点/偏差触发 ⟹ **冻结=已发生的现实**（实绩覆盖计划——实际 8:25 开工，新计划从 8:25 接续）+ 带符号差分 + baseRevision 409 防互踩。内核 `solve_with_maintenance(frozen=)` 两求解器同源透传（1.30.0） |
| **专业版工程面** | ✅ | API key 认证（`APS_API_KEY`，未设=关闭+显式警告）+ SQLite 持久化（`APS_DB_PATH`：会话基线/滚动历史）+ Dockerfile/compose + GitHub Actions CI（1.30.0 —— 此前是家族三仓中唯一无 CI/无 Docker 的） |
| **家族闭环实验** | ✅ | `scripts/family/`：①计划⟹ILESP TaskBody 派工契约（缺站点映射=跳过+告警）②CPS 影子扰动⟹推演输入（故障→保养窗口/急单→whatif delta）③baseRevision 家族协议 PoC（两系统两条路径独立算令牌⟹同值）。各带 `--self-test`（1.30.0） |
| **计划 vs 实绩对账** | ✅ | `aps compare 输入.json --plan plan.json --actual 报工.csv`：逐工序偏差（开工/完工/时长/换设备）+ 按设备汇总 + 工单完工偏差 + **换型假设 vs 实绩间隙**（校准的数据源）。四态如实报告：配对 / 实绩缺报 / 计划外 / **计划未排但现场干了**；实绩为空或缺 horizon 响亮失败，不出空报告（1.29.0，实绩回路第一步——**对账先于学习**） |
| **拖拽重排（交互式甘特）** | ✅ | `aps_kernel.reschedule_move(data, MoveRequest(...))`：把一道工序拖到新位置，**前道原位钉死 + 后道按同一位移量顺延**，其余交 CP-SAT 重排 ⟹ 完整新计划 + 差分报告。⭐ 差分三档口径：`moved`（全部位移，**带符号**，含被提前的）/ `pushed`（只取正，向后兼容）/ `flipped_late`+`new_late`（准时变拖期）。⭐ 诚实闸门 `moved_honored` **逐条核对**资源+槽位+起点，无解时如实报 `INFEASIBLE` ⟹ 前端必须提示「拖拽未生效」而非假装成功（1.22.0）|
| **行业分册（专业版规则库）** | ✅ | `src/aps_kernel/data/industries/*.yaml` 可执行配置（**随 wheel 分发**，pip 用户 `aps industries` 直接可见）+ `aps industries` / `solve --industry`。**注塑册**（1.18.0：非对称换型矩阵 + 四层成本 + 保养 + 首检/烘料）、**冲压册**（1.19.0：同吨位 12min / 跨吨位 45min + 首件检测 2h）、**机加班**（1.22.0：**换型三档** 45/60/90min + 组名三段式约定 + Aethon 实测的固定准备 15min）。每条参数标来源；应用后结果必须改变（测试锁住） |

---

## 三个设计立场

### 1. 诚实高于漂亮

`OPTIMAL` 只在**真正证明最优**时才标；`FEASIBLE` 必带真实 gap；
超时回退贪心解时 `diagnostics["solver_fallback"]` 明确标注来源；
**全部未排时标 `INFEASIBLE` 而非 `OPTIMAL`**（避免"看起来排好了"）。

> 这直接对应论文《Formalize, Don't Optimize》的三个统计口径：
> **返回结果率 / 验证通过率 / 已返回中通过比例** —— 分母不同，不可混比。

### 2. 复核器是必需品，不是锦上添花

`validator.independent_validate()` 用**输入数据重算**（时长、槽位、日历、
换型、设备资格、技能资格、**依赖满足**），**不信任求解结果自报的值**。这不是防御性冗余 ——

> 开发中它抓到过**槽位重叠 48 处而求解器报 `OPTIMAL`**、
> **makespan = 2.3e18 的垃圾值**（`UNKNOWN` 时仍读未赋值变量）。

### 3. 基准必须公平

所有基线必须在**相同约束集**下比较。曾实现一个无视日历/工序先后的 SPT 基线，
得出「SPT 比 CP-SAT 还优」的**颠倒结论**（vsSPT = -203%）。

> 非法基线比没有基线更糟 —— 它会得出完全相反的结论。

---

## 🏗 分层架构：本包的位置

博客园《CP-SAT 排产、排程、排班》：

> 「APS（长周期规划）+ RTS/RTD（实时派工）**双层架构是业界最佳实践**」
> 「前一天做的排程，第二天全乱套」—— 排程 ≠ 派工 是经典误区

```
┌─────────────────────────────────────────────────┐
│  上层（aps-platform / 本包之外）                  │
│  · MRP / 采购 / 库存                              │
│  · APS 长周期计划（天/周）                        │
│  · RTS / RTD 实时派工（分钟级）  ← 不在本包        │
│  · MES 执行回写 / 甘特图 UI                       │
└─────────────────────────────────────────────────┘
                ↕ ScheduleInput / ScheduleResult
┌─────────────────────────────────────────────────┐
│  aps-kernel（本包）—— 求解内核，不含流程            │
│  ✅ 数据模型 / 输入校验                            │
│  ✅ 规则引擎（7 规则 + 8 链）                     │
│  ✅ CP-SAT 精确求解 + 贪心兜底                    │
│  ✅ 冻结窗口（支持增量重排）                      │
│  ✅ 独立复核器（13 项）                          │
│  ✅ ε-约束 trade-off / 冲突诊断 / 基准            │
│  ❌ 不做派工、不做 UI、不做持久化、不含 LLM         │
└─────────────────────────────────────────────────┘
```

⚠️ **为什么派工不在本包**：派工是**高频决策**（分钟级刷新），
需要实时状态推送与人工干预；本包是**低频决策**（计划级），
追求确定性与可审计。把两者混在一个包里会同时失去两者。

⚠️ **本包负责「证明这个计划可执行」，不负责「生成甘特图」**：

> 「排产的难点从来不是生成一个计划，而是**证明这个计划在约束下可执行**。」
> —— 《LLM 不会给你最优排产，求解器会》

---

## 版本与兼容性

| | |
|---|---|
| 当前 | **1.33.0** —— 功能优先迭代期，API 会随功能演进 |
| 含义 | ⚠️ **1.0.0 的 API 冻结承诺已于 2026-10-17 取消**，现按功能优先迭代 |
| 变更记录 | [CHANGELOG.md](CHANGELOG.md) —— 含破坏性变更与迁移动作 |

---

## 快速开始

### ⭐ 不会写 JSON？走这条路（1.9.0 起，给计划员用的入口）

```bash
pip install aps-kernel

# 1) 生成一套带示例数据的 CSV 模板（五张表）
aps demo mydata

# 2) 用 Excel 打开 mydata/ 下的 CSV，改成你的数据
#    （jobs / operations / operation_resources / resources / calendar）

# 3) 求解 + 出甘特图 + 出可贴回 Excel 的结果 + 求解证书 + 复核报告
aps solve mydata/ --solver cpsat \
    --gantt gantt.html --csv result.csv \
    --certificate cert.txt --validation-report audit.html

# 4) 双击 gantt.html 看甘特图；audit.html 看独立复核的 13 项
```

**三个产物各回答一个问题**：

| 产物 | 回答 |
|---|---|
| `gantt.html` | 计划长什么样 |
| `cert.txt` | 这个解**证明过吗**（OPTIMAL 才写「已证明最优」，贪心解写「未经求解器验证」） |
| `audit.html` | 独立复核器逐条验算的结果（不复用求解器任何中间结果） |

全程**不需要写一行代码、不需要懂 JSON**。五张表都是扁平 CSV，
Excel 直接改；导入时缺列/类型错会**点名到文件和列名**，不会静默取默认值。

### 程序员路径（JSON / Python）

```bash
# 0) ⭐ 上线前先体检（核对工时/BOM/日历/换型矩阵四张底账）
aps health input.json --bom bom.json --inventory stock.json

# 1) 看内置规则链
aps chains

# 2) 求解（贪心，快）
aps solve input.json --chain default

# 3) 求解（CP-SAT，可证 OPTIMAL）
aps solve input.json --solver cpsat --time-limit 30 --gantt g.html --csv r.csv

# 4) 排不下时诊断原因（最小冲突集）
aps explain input.json

# 5) 基准验证（规则链 vs SPT vs CP-SAT）
aps benchmark --sizes 5,8,10 --chains default
```

> `aps health` 的退出码可直接接 CI：`0` 可上线 / `1` 需补数 / `2` 阻断。

```python
from aps_kernel import schedule, solve, CpSatOptions, independent_validate

# 贪心（快，不证明最优）
result = schedule(data, chain="default")

# CP-SAT（可证 OPTIMAL）
result, stats = solve(
    data, options=CpSatOptions(time_limit_seconds=30, workers=8),
)

# 独立复核 —— 不信任求解器自报
checks = independent_validate(data, result)
assert all(ok for _, ok, _ in checks)
```

---

## 🤖 AI 集成（两条路，按场景选）

> ⭐ **本包在完全没有 LLM 的环境下 100% 可用** —— 核心（求解/复核/诊断）
> **零 LLM 依赖**，`pytest tests/` 不需要装 byoe、不需要 API key、不需要网络。
> AI 能力是**可选增强**。

### 路径 A：进程内类库（**AI 副驾 / 对话式排产，推荐**）

同进程调用，**数据留在 Python 侧**，LLM 只发小增量：

```bash
pip install 'aps-kernel[byoe]'    # 可选依赖，MIT
```

```python
import byoe
from aps_kernel.byoe_bridge import build_aps_agent

agent = build_aps_agent(data=my_schedule_input)
print(agent.chat("这周产能够吗？插一个急单会挤掉谁？"))
```

**为什么类库比 MCP 更适合 AI 场景**（两条硬伤，均实测）：

| | MCP 路径 | 类库路径 |
|---|---|---|
| **数据搬运** | 3 单的 `ScheduleInput` JSON = **27,908 字节**；`tools/call` 无状态 ⟹ LLM 每次全量搬 | Python 侧持有数据集，LLM 只发**小增量**（插单只传一个新工单） |
| **超时** | byoe 的 MCP 客户端**硬编码 30 秒** ⟹ 需 `async_mode` + `task_id` 轮询 | 进程内直调，**无此限制** |

提供 6 个会话工具：`aps_solve` / `aps_whatif_insert` / `aps_plan_summary` /
`aps_explain` / `aps_health` / `aps_validate`。

### 路径 B：MCP server（跨进程 / 跨语言 / 任何 MCP 客户端）

```bash
aps-mcp        # 或 python -m aps_kernel.mcp_server
```

```python
import byoe

agent = byoe.create_agent(
    model="deepseek-v4-flash",
    api_key="sk-...",
    mcp_servers=[{
        "name": "aps",
        "command": ["aps-mcp"],
        "allow_tools": ["aps_*"],
    }],
)
```

> ⚠️ MCP 客户端超时 30 秒 ⟹ 大算例请用 `options.async_mode=true`
> （立即返回 `task_id`），再用 `aps_get_result` 轮询。

### 两条路共用同一份实现

工具定义在 `aps_kernel/tools.py`（**协议无关层**），MCP 与类库只是两个宿主
⟹ 结构上杜绝「口径分裂」。

---

## 已知局限（诚实列出）

| 局限 | 说明 |
|---|---|
| ~~`Job.due_date` 只能表达天~~ | ✅ 已修复（v0.10.0）：改为 `date | datetime` 联合类型，支持小时级交期。用 `due_offset_from_horizon()` 计算偏移（**不要**用 `.days * 1440`，会丢小时） |
| 交期需**整日或整时** | 建议传 `datetime`；传 `date` 时按当天 00:00 算，不是「当天结束」—— 与部分 APS 的约定不同，转换时请留意 |
| 大规模 gap 仍大 | **实测（1.8.0，12 机 24 槽位，30 秒预算）**：CP-SAT 约 **50 工单以内达 OPTIMAL**，80 工单起超时回退贪心。**已修的根因**是 presolve 吃光预算（`branches: 0`，搜索从未运行）—— 熔断后 3 工单快 8 倍、20 工单从 UNKNOWN 变 OPTIMAL/6.9s。**仍存限制**：makespan 级本身在 30 秒内证不了最优（裸模型能 OPTIMAL，说明瓶颈在该目标的建模而非 presolve，属下一步优化对象）|
| ~~换型为**静态规则**，非序列相关~~ | ✅ 已修复（v1.4.0/1.5.0）：换型时间**真实占用产能**（此前只记录不预留，计划现场执行不了）；A→B 与 B→A 可不同（换下的模具比装上的更重是物理现实）。仍不支持「A→B→C 链式换型」的组合优化 |
| ~~缺**拆批合批**~~ | ✅ 已修复（v1.5.0）：`split_input` / `merge_compatible_jobs`。**工时按数量线性缩放**（不缩放时拆 4 批 makespan 120→480）。合批守交期红线，默认关闭 |
| 换型建模假设「同槽位同组成块」 | CP-SAT 的换型约束是**充分非必要**的（排除交错排法），非等价改写。换型极贵时该假设成立，但这是真实限制 |
| ~~**工序必须放进单个日历窗口**~~ | ✅ 已修复（v1.21.0）：`Operation.interruptible` 支持跨窗口续排（午休/夜间停机时暂停加工）。⚠️ 约束：**跨度独占槽位**（工件不下机，段间空隙不能插别的活）；**首段必须容得下固定准备**（`setup_seconds` 装夹/调机不可打断）；各段长度之和 == `ceil(工时) + 准备`。两个求解器同口径 |
| ~~模具**无寿命/维护周期**建模~~ | ✅ 已修复（v1.15.0）：`Resource.maintenance` + `calendar.maintenance_schedule`（日历层挖洞，两求解器+复核器同口径）。⚠️ 周期按**自然日**近似，非按累计加工量；「这副模还能用几次」的寿命计数仍未建模（冲压按冲次保养同属此列，P2-8） |
| ~~技能只有**资格过滤**，无池容量~~ | ✅ 已修复（v1.16.0）：`ScheduleInput.skill_pool`（厂级几人 = 几并行），CP-SAT/贪心/复核器三方同口径。⚠️ 多工种共享同一设备的并发上限仍未建模（专业版） |
| 无持久化状态 | 每次求解无状态，冻结窗口需由调用方传入 |
| 合成 demo 交期偏宽 | demo 默认交期 = horizon+5 天 ≫ makespan → 拖期恒为 0；验证拖期逻辑需改用紧交期 |
| 体检的**可执行率是估计值** | 基于静态校验，不检查「现场是否会临时变更」。cp_sat_demo 实测 44%，本估计通常偏乐观 |

---

## 安装与依赖

- Python ≥ 3.11
- 运行时依赖：`ortools >= 9.12`、`PyYAML`
- **仅发 wheel**（`py3-none-any`），不发 sdist

## License

MIT
