Skip to content

PHP 更新日志 ​

当前版本 v1.4.1 · Packagist(mldong/jeeflow-php,独立 1.x 版本线)· 仓库 mldong/jeeflow-php · Releases 版本日期以本仓 git tag 为准;跨语言对齐脉络见 更新记录总览。

v1.4.1 — 2026-10-31 ​

「退回修改、重提直返」首轮发版(tag v1.4.1=commit fa2dfd0,出口契约修复 5e28432)。 条文见 规范 04 引擎操作「退回修改、重提直返」节。

  • 新增:reapplyMode 节点属性与非法值解析期报错、submitType=6 直返建带 _reapplyContext 的申请待办、submitType=5 重提直接回来源节点、_branchCtx 分支归属 与汇合等齐判据、保留键入口剥离与同实例串行化。实现落点:packages/core/src/Support/ReapplySupport.php + packages/core/src/JeeflowEngine.php。
  • 变更:带标记的申请待办在 executeAndJumpTask/executeAndJumpToEnd/ executeAndJumpToFirstTaskNode 入口一律先拒(文案与 java 逐字一致)。
  • 修复(ext 回退契约被新保留键打破——本栈是最先报红的一家):建单无条件写入 _branchCtx(空分支也写 []),而内存仓与 PDO 仓两处 taskRow 的 "任务变量只剩引擎控制键 ⇒ ext 回退实例变量"判据只认 isFirstTaskNode ⇒ 三条既有 内容级用例(PdoSqliteTaskRowExitTest/JeeflowFacadeIssue82Test/TaskFormData189Test) 当场红:期望实例变量,实得 {isFirstTaskNode:false, _branchCtx:[]}。其余七栈同病但没有 内容级断言,只有本栈的尺子照得出来——修复因此抬成八栈共同动作。判据收成一枚 ReapplySupport::projectTaskExt(两处出口共用,严禁第二份判据),回退取副本并合回 _reapplyContext(前端「重新提交后返回:X」的唯一取数口)。
  • 注(上一版补记):v1.4.0 那次(PHP 运行时下限抬到 8.2+demo 镜像升 8.4.27 并关危险默认项) 没来得及在本页留节,此句补记,不代表本轮内容。

v1.3.38 — 2026-10-17 ​

audit8 R110(tag v1.3.38)。

  • 新增(删除定义守卫):processDefine/remove 删除前校验任何实例存在即拒,批量先整批校验;仓储接口与 PDO/内存实现补 hasInstancesByDefineId。

PHP 引擎独立发版,版本号不与四语言对齐,对齐的是引擎语义与 API 契约。2026-08-11 首发 v1.0.0。环境要求:PHP 8.1+ / Composer 2.x。

v1.3.37 — 2026-10-16 ​

audit8 R93(丙-10 php 半边)修复(tag v1.3.37,引擎 commit f74095b)。

  • 修复(决策零命中的异常形状):decision 节点无任一出边命中时抛的 JeeflowException, 此前文案是自家短语、内部码缺省 ⇒ 与其余各栈对不上。现钉成同码同串: decision节点无法确定下一步执行路线 + 内部码 20010001(规范 02 §5 的无兜底失败下限,指向规范 06 §4.6 义务 2 那一档)。
  • 不受影响的部分:门面信封一直是 99999999(error() 硬编码),所以对外错误码从未失守; 本笔补的是异常对象那一半=跨栈对账与直连引擎调用方读到的 code/message。

v1.3.36 — 2026-10-15 ​

issues/234 丙-9(audit8 R90 拍 A):decision 节点多条出边表达式同时为真时,改首条真边独走 (tag v1.3.36,引擎 commit 5e519da)。对齐 规范 02 §5 与 go/python/node/rust/moon 五栈多数派。

  • 行为变更(决策路由):此前 foreach 无 break=多真边全部执行(多路并行流转);存量里依赖 "多真边齐走"的流程受影响,升级前自查 decision 节点出边表达式是否可能同时为真。
  • 无兜底时的失败形状(无法确定下一节点,码 0)本轮不动——兜底语义另案待拍板。

v1.3.35 — 2026-10-14 ​

issues/204(audit8 R84):processDesign/detail.his[] 出口键归一 camelCase(tag v1.3.35, 引擎 commit 3ca1df1)。规范 06 §2.1 立法「出口键一律 camelCase」随行。

  • 修复(用户可感知):his 腿原样直投裸 PDO 行 ⇒ 蛇形键(create_time 等)整列缺席 camel 键、 唯一在场的还是微秒尾串;现经 designHisRowToMap 归一(字段集逐字对齐 java ProcessDesignHis), 微秒尾经 fmtTime 折进 §2.4 格式。
  • 附带:composer 页 v1.3.35 节本应随 R84 轮上线,漏更至本轮回填(index 表同批 1.3.34→1.3.36)。

v1.3.34 — 2026-10-13 ​

issues/194 收口:flow.auto/flow.admin 哨兵大小写两派收口(tag v1.3.34,引擎 commit 4ba655d)。 条文见 规范 04 · 引擎核心操作(明文「忽略大小写」)。

  • 修复(用户可感知):addUserInfoToArgs 此前用精确串比对认这两个哨兵 ⇒ 宿主传 Flow.Auto/ FLOW_ADMIN 之类的异写时,哨兵被当普通用户去查 IUserProvider,代执行与管理员语义失效。 本栈栈内还有两套口径,一并收敛为 strcasecmp。
  • 同批:rust(v1.0.41)与 MoonBit(0.1.44)三引擎,rust/php 两壳+moon 插件,2 镜像+moon 通道全晋升。
  • 判据:两处口径各钉异写档+变异对照。

v1.3.33 — 2026-10-13 ​

issues/191 收口:事件 fire 派发挪到 COMMIT 之后(tag v1.3.33,引擎 commit 3076dca)。 条文见 规范 11 · 事件 §11.3.1 与 规范 12 §12.3.1。

  • 修复(后果级):本栈 fire 在事务内派发且无 afterCommit——中途失败时事务回滚、 但站内信/抄送消息已经发出去了(用户收到一条不存在流程的通知)。探针实证:中途失败 ⇒ 库无行、监听器仍收到码 5。
  • 修法(引擎+壳两段):引擎委托模板补可选 afterCommit(无该件时行为不变,兼容既有宿主); Laravel 集成壳接 DB::afterCommit。
  • 判据:4 枚真库判据(修前红两条)+变异对照;全量 684→688。
  • 传播面:php→laravel,1 张镜像(候选 54/0/0→晋升)。

v1.3.32 — 2026-10-13 ​

issues/190 收口:jumpAbleTaskNameList 改按历史行过滤(tag v1.3.32,引擎 commit 9dd6f4b)。

  • 修复(直接作用于 JUMP 可达面):此前返回全模型任务节点——凡流程图上有的任务节点都算「可跳转」, 包括从没走过的分支。本版按 FINISHED(20) 历史行组装,排会签+去重。
  • 基准:连内置版 boot2 都按历史行过滤,本栈与两侧基准同时相反(八栈现读本栈独家)。
  • 现读更正:卡面「findDoneTasks 两条腿可用」不准确——本栈无 findDoneTasks,取数走历史行那一腿。
  • 判据:三枚+变异 M1/M2 咬合;全量 683→684。

v1.3.31 — 2026-10-13 ​

issues/189 收口:列表行 taskFormData 从硬编码空对象改真算(tag v1.3.31,引擎 commit 4f5ac56)。

  • 修复(用户可感知):processTask/page 每行的 taskFormData 此前恒为 {}(第六派形状), 列表页拿不到表单字段;单条 processTask/detail 却是真值——同一份数据两条腿两个答案。
  • 修法:core 新增 Util\FormDataUtil::of 单点,门面/内存仓/PDO 仓三条腿同源。
  • ⚠ 判定支点提醒:本栈出口形状要读仓储腿才能定,只 grep 门面会误判(列表端点 taskFormData 恒 {})。
  • 判据:三枚两腿+变异;全量 680→683。

v1.3.30 — 2026-10-13 ​

issues/188 收口:HandlerRegistry::listHandlers 补 order 升序(tag v1.3.30,引擎 commit 5b354ad)。 条文见 规范 08 场景 22(逐字要求升序)。

  • 修复:本栈 order 只当数据存、不当排序判据 ⇒ 「场景有、实现无、门禁无」三缺;八栈现读其余七家全排, 本栈独家缺。
  • 修法:补一行 usort(PHP 8.0+ 稳定排序,对齐 java TimSort 的稳定性)。
  • 判据:两枚判据+变异 M1/M2;全量 678→680。
  • 同族欠账:元数据侧(spec07 的 key 表与注册表四法)当时整片无门禁格,另案补。

v1.3.29 — 2026-10-13 ​

issues/186 收口:补上第四能力 listHandlerTypes(tag v1.3.29,引擎 commit 9041370)。 条文见 规范 07 · 元数据与注册表。

  • 新增:spec07 的四法在 node/php 塌成三法,本栈补 listHandlerTypes;口径对齐 java= 某类型在场 ⟺ 该类型 listHandlers 非空,去重+首次注册序。
  • 现读更正:涉案确数 2 家,八栈零生产消费者(能力面缺口,非页面缺功能)。
  • 判据:新格+变异;全量 674→678。

v1.3.28 — 2026-10-13 ​

issues/180 收口:abandonTask 不再连带把整单置 99(tag v1.3.28,引擎 commit 3ceece5)。

  • 变更:删掉实例 state 写 ABANDON 的那一处——任务级废弃只废任务。对齐 spec 与 go/python/node; 五栈该方法全部零生产调用者(调用面 grep 仅定义处命中)⇒ 现生产零行为变化,收的是「一旦接上就顺手废整单」的潜伏形状。
  • 同批:java/php/rust/csharp/moon 五栈一次收(java v1.8.49 等),6 壳+moon 插件、6 镜像+moon 通道全晋升。
  • 判据:三枚(废弃后实例仍进行中/其余待办可见/整单废弃另走一条腿)。

v1.3.27 — 2026-10-12 ​

issues/177 收口:会签完成条件读形补 properties.field 兜底(tag v1.3.27,引擎 commit e97f206)。 条文见 规范 08 场景 43「字段权限族」。

  • 修复(用户可感知):设计器把 countersignCompletionCondition 写在嵌套形 properties.field, 模型解析只读顶层 ⇒ 阈值恒读不到,「两人同意即放行」实际要等满员。本版从 $field 兜底取。
  • 本栈在名单里的只有这一处:候选人两键那族(go/py/node/rust/moon 五栈)本栈不适用—— 现读消费腿不回查 ext,属另一条轴。
  • 判据:两枚+变异;复跑 674 OK(39 skip)。

v1.3.26 — 2026-10-12 ​

issues/176 收口:startAndExecute 自动办理腿 operator 改 flow.auto(tag v1.3.26,引擎 commit 2a1b289)。

  • 变更(用户可感知):一键发起并办理的那条任务办理人记成系统哨兵,真实发起人不再同时出现在「我已办」。
  • 判据:跨栈门禁 L2-43 同轮落格。
  • 传播面:php→laravel;本轮总传播面 8 引擎→13 壳+moon 插件→14 张镜像全晋升。

v1.3.25 — 2026-10-12 ​

issues/145 事务七条债 · php 切片(该案第 7 条收口,tag v1.3.25,引擎 commit b5be7c4)。 条文见 规范 12 · 事务与持久化。

  • 变更:inTx 加 join 支(已绑定则并入最外层,不另开连接/不重复 BEGIN)+门面把整次 dispatch 包进事务+模板 inTransaction 探测;普查里「persist 业务表写腿并入动作事务」那一格的 php 腿同批。
  • 判据:真库 tier 档+逐处变异对照。
  • 传播面:php→laravel,1 张镜像晋升。
  • ⚠ 后续欠账提醒:模板接上门面之后,fire 时点是否要同步后移需逐栈重扫(本栈已于 v1.3.33 收口)。

v1.3.24 — 2026-10-11 ​

issues/165 A+166 A(种子+demo)收口(tag v1.3.24,引擎 commit 1ae20bb)。条文见 规范 04「放行表达式的求值原料」。

  • 变更(用户可感知):CountersignHandler.buildCountersignVars 的求值原料同时挂裸名 (nrOfInstances / nrOfActivateInstances / nrOfCompletedInstances)与前缀键(csv_{node}_*, 保留兼容)。改前按文档/设计器形状 #nrOfCompletedInstances>=2 配的并行会签在生产求值器上恒 false (WfExpressionEvaluator 的 # 臂剥前缀精确查表查不到裸名,?? 0 后恒不达阈值)。
  • 测试基建:夹具 SimpleExpressionEvaluator 摘 str_ends_with 后缀桥(#裸名 精确查表, 对齐生产形状);新增 CountersignBareNameI165Test(内联夹具,裸名 2/3 放行+前缀键兼容), 全量 662/662 绿+变异对照。活栈实证:php demo F2(07-countersign-ratio 四人档)2/4 即放行。
  • 种子/demo:F5/F8/F9 补 finalAmount=8000(issues/166);seed_define_name 从 15 文件时代 映射改写为 16 文件 canonical(原错位使 I15 卡 with-reject);demo-slim 此前没注册表达式求值器 SPI(决策一律抛"未注册"),补 DemoExpressionEvaluator(形状逐字对齐生产件)+两处 bootstrap 注册。
  • 不变:php 是决策零命中的报错派(无法确定下一节点),本版零改动。

v1.3.23 — 2026-10-10 ​

issues/156 收口随 153/154/155 镜像轮发版(此前 changelog 漏记,此处补一行):highLight 模型补全腿—— 成员 id 被 PHP 键折叠成 int,TypeError 遭 swallow 吞成 nodeProgress 整体为空。

v1.3.22 — 2026-10-10 ​

issues/153·154·155 的 PHP 侧四条分叉收口(Packagist,引擎 commit 963211f)。条文见 规范 06 §4.6。

  • 新增:highLight 补上整条模型路径补全腿——collectPath / evalDecisionExpr 逐字照 Java 与 Go 的形状: 从 start 沿输出边递归、遇活跃节点停止深入、决策节点的带表达式出边先求值(求值为 false 的分支, 边名与目标节点都不收),visited 跨分支共享。此前本栈 historyEdgeNames 声明成空数组后原样出口, 不产生任务行的网关/结束节点全丢。
  • 变更:getAssigneeTextData 的 label 并派为其余七栈形状 节点显示名:用户id (本栈此前独家出 节点显示名:真实姓名,是八栈里唯一的异类)。
  • 新增:approvalRecord 补首列 id(显式 (string))凑齐九键;取数路径就地按 id 数值升序 (自写数值比较,不对 19 位 id 做 (int) 强转防溢出),未动聚合根的共享方法。
  • 变更:视图端点在实例不存在时改出空数组(原先抛错)。
  • 本栈本就合规、只补用例钉住:ccList 默认分页 1/10、ext 空档 {} 无实例变量回落。
  • 降级档说明:表达式求值复用引擎同一个 ExpressionEvaluator SPI 口,SPI 未注册时整档判 false (不高亮任何决策分支),注释已写明那是降级档而非常态。

v1.3.21 — 2026-10-08 ​

issues/152 委托三件收口(Packagist,引擎 commit 1fd8ee5)。规范条文见 规范 06 §2.5 口径表 与 §4.5「processSurrogate/page 归属不变式」, 判据基线=规范 08 用例 38–41。升级前两处用户可感知的行为变更必读(见下)。

  • 新增:processSurrogate/page 的归属不变式落到引擎自己身上——门面按 §2.5 把归一后的 operator (缺键/空串/全空白 ⇒ demo 缺省 user1)作为 t.operator EQ 下发,形状与本栈 instancePage 一致; 仓储侧补第二层(SQL 侧 AND 1=0、内存侧判不命中),内存仓与 SQL 仓同答案。 此前这条语义全靠集成壳注入 operator(换宿主/直调 SPI 即退化成全库台账,vben5 前端本就不传)。
  • 变更:归属条件的缺失档与空值档同判——绕过门面直调 pageSurrogates 时,t.operator 那条 EQ 值为空或整条没给都返回空页,不再"这条条件不加"放出全库;只收归属列, m_LIKE_* 那套"空值当没填"的可选过滤放行原样不动(与 §2.5 抄送侧同一条尺子)。
  • 修复:写侧授权人三档归一。processSurrogate/save 收到空串/全空白 operator 时不再落进 operator (那种行是死行:getSurrogate 的 WHERE operator = ? 永不命中,台账看得见、待办永不并人); save 缺省档落归一值,update 缺省档保留原授权人不变。
  • 不变:委托查询的作用域优先级(精确优先)与择优顺序(先按 id 取最新一条再交判据裁决) 维持 v1.8.2x 起的既有立法(issues/123 收口形状),与内置 mldong-wf 版方向相反—— 差异与迁移动作已写进 §4.5「与内置版(mldong-wf)的三条方向差异」。
  • ⚠️ 行为变更(用户可感知):① 集成方若曾依赖"processSurrogate/page 不带 operator 返回全库", 升级后该档只返回归一缺省 user1 名下的行;② 直调仓储的调用方若不给归属条件,将拿到空页。 jeeflow-ui 与 vben5 两条前端腿都经门面且各栈已实测零回归。
  • 测试:仓内 T0 五档判据(作用域优先级/停用不自愈/自委托/写侧三档/分页归属两层), 每档配真值档阳性对照;摘掉兜底判据必红。

v1.3.20 — 2026-10-02 ​

本版除跨栈对齐批之外,还收掉了 issues/70 第 10 条(本栈 schema-mysql.sql 副本长期不随编辑源分发)。

  • 新增(issues/115 §3-8):门面第 47 个 action processTask/removeTaskActor; §3-8 主键档并轨——0/负数走缺参数档而不是"任务不存在"(随 spec 语义 8)。
  • 修复(issues/137 §3-1/§3-6/A §3-4+§3-9/D/E):门面固定文案+判别式五条;删除腿两形并集; 实例级 expire_time 按定义级表达式求值+写点④两格;相对档前缀判非负(tryInt 判负, [+-]?\d{1,18} 不收窄)+两端空白容忍。
  • 变更(issues/137 §3-10,三步拉平):packages/repository-pdo/sql/schema-mysql.sql 由 手写分叉件改为编辑源逐字分发件(sync-schema.sh 新增本栈目标,LF 分发 + 仓内 *.sql text eol=lf); 为此先把真库测试种子里 66 处/22 种非数字 id 归正成数字串(列类型是 BIGINT, 写 'def-1' 在 STRICT_TRANS_TABLES 下实测报 1366 HY000——旧副本没有那 15 个 BIGINT, 所以那份测试长期"看着是绿的"); 其中三条故意留非数字作负向守卫(断言的是"非数字入参要响亮报错")。
  • 文档(§H1/§3-11):注释诚实化——tryInt 本来就没有 int32 上限,别把没做的事写成做了; 误配档改写成"八栈一致落穿"。
  • 测试:全量 640 tests / 4832 assertions / Skipped 0(真库腿 REQUIRE_MYSQL=1 连 160, 旧的 37 格 skip 全部真跑);建表底座是重建后的 jeeflow_test(15 列 BIGINT/14 索引/8 COMMENT, 与编辑源逐字一致)。发版后 demo 站 MySQL 腿 16/16、9/9、8/8 + 冒烟"40 action 核心路径验证 OK"。

v1.3.19 — 2026-09-30 ​

  • 新增(issues/142 A 批):从零补齐 custom 记录类一档——CustomModel/CustomNodeParser/ CustomHandlerInterface/CustomHandlerRegistry(注册表挂既有 ServiceContext 定位器)+历史行 真落库。此前 ModelParser 只注册七档、无 custom 档 ⇒ snaker:custom 节点连同出边在解析期被 吞掉,且被丢节点的入边 target 为 null ⇒ 办理动作硬崩(本栈是三派里崩得最响的一派)。 methodName 找不到归"配错档"记日志继续(豁免面边界="这一行处理器代码有没有被执行过")。
  • 修复(issues/143):TransitionModel::execute 开头加 null-target 守卫 ⇒ 记一条带 from/to 的 WARNING 后令牌停住,不再 Call to a member function execute() on null 打崩办理。
  • 变更(issues/142 B 批 · spec 06 §2.11):CcActorUtil 新增 normalizeActors(集合腿)/ normalizeActor(标量腿),既有 normalize() 退化为一行转发 ⇒ cc 三支与任务三支从此 不可能分叉;类名不改、接口成员零增加。四处落点:加签腿(旧串腿 array_filter 无回调= 假值判据、实测吃掉 '0')、CreateTaskHandler::nextNodeOperator 两臂换单点(顺带拆掉外层 (string) 强转)、JeeflowFacade::updateCCStatus operator 归一、两仓 removeTaskActor 删除位按归一值比较(' 8601 ' 删得掉 8601;归一后为空 ⇒ 早退零删除)。 破坏面(八栈独一份的违反档收口):actorIds 为空由 code=0 改成报错; updateCCStatus 空 operator 档对齐 java 基准——回落 user1 标记自己的行,不是报错。
  • 测试:全量 phpunit 558/4118/0/Skipped 37(基线 521/3892 只增不减)。

v1.3.18 — 2026-09-29 ​

  • 改造(issues/132):case 名按 §11.3 规范名对齐(INSTANCE_START / INSTANCE_END / TASK_START → PROCESS_INSTANCE_START / PROCESS_INSTANCE_END / PROCESS_TASK_START,码值 1/2/3 不动), 并补 TASK_COMPLETE(5) … INSTANCE_TERMINATED(9);旧 case 名以枚举常量保留一代 (public const INSTANCE_START = self::PROCESS_INSTANCE_START; 三支)——PHP backed enum 不允许两个 case 同值,故用常量承载,cases() / from() / ->name 一律不受影响。
  • 修复(R2-1,照 java 移植):EndProcessHandler 由就地 fire 改成 登记 → 级联上收 → JeeflowEngine 两处 flush(发起路径与 persistTasks 之后各一次)。 顺带抓出并修掉本栈同病:级联里父实例 finish() 后无人写它——内存仓共享对象引用照不出来, 真库下父实例永远停在 10;flush 时对非本 execution 的实例补一次 updateInstance 再播。
  • 修复(issues/138):ccList 行形状三要件对齐 boot2 基准——行必须来自实例表(带 id 主键)、 operator 必须是流程发起人而不是查询者本人(谓词 t.actor_id → cc.actor_id), PDO / InMemory / 门面三处同改。
  • 测试:T0 418 tests / 3268 assertions(37 skip 是无 MySQL 环境的正常档); T1 REQUIRE_MYSQL=1 433 tests / 3538 assertions / 0 失败。变异:改回就地 fire ⇒ 新时机件 4 支全红而旧 recorder 全绿(证旧套件失明);删级联上收那一行 ⇒ 只红子流程那一支; 删别名常量 ⇒ Error: Undefined constant … INSTANCE_START。

v1.3.17 — 2026-09-29 ​

  • 修复(issues/134 · 撤回不校验实例状态):对已办结/非进行中的实例调撤回,改前会被静默改写—— 实例 state 被写成 30 且返回 code=0(症状现场:boot2 生产镜像 code=0 msg='成功',state 20→30)。 聚合根 withdraw 入口加实例态守卫:state != 10(进行中) 一律拒,内部码 20010009,被拒时 实例与任务行零改写、不落库;出口按 issues/121 口径透出 code=99999999 + 逐字文案 「流程实例非进行中,无法撤回」(内部码不进 msg)。任务行层面的既有保护(spec 06 的"20/40 任务行 不改写")原样保留,实例级守卫排在它之前。落点:Domain/ProcessInstance.php::withdraw 首行守卫(码进 @throws 注释)。phpunit 402 tests / 3135+ assertions / 0 fail(基线 399)。
  • 修复(issues/130 · 委托 enabled 脏值默认方向):判据收窄为只认数值 1(is_int && === 1); 本仓 MySQL 套件 ATTR_EMULATE_PREPARES=true 会把 INT 列回读成 '1',故在仓储读侧 newestSurrogateInScope 交判据前调 hydrateEnabled() 还原(只还原规范整数串 -?(0|[1-9]\d*), 'abc'/'1.0'/' 1' 不还原)——不还原的话 MySQL 宿主的委托会整体静默判废。门面 processSurrogate 写侧 _to_int 归一保留。

v1.3.16 — 2026-09-28 ​

  • 修复(issues/126 案 A):本栈原先只把到期原串搬到实例级,注释自承"不处理变量替换",任务行五处一个都没赋。 新增 packages/core/src/Util/FlowUtil.php 的 processTime()(三档;相对档前缀非整数走落穿→null,与 Java 抛异常是故意差异), ProcessInstance.php 的 applyExpireTime / applyNodeExpireTime,写点 :191 普通建单 / :227 串行首位 / :239 并行全员 / :299 回退新建(随行 $vars)/ CountersignHandler.php:163 串行推进位。
  • 测试 tests/Core/ExpireTimeOnCreateTest.php 六格;phpunit 全量 Tests: 394 / Assertions: 2936 / Failures: 0 (37 skip=改前基线同数),T1 --filter MysqlSmoke OK (7 tests, 84 assertions)。 变异对照两层:求值换 date('Y-m-d H:i:s') ⇒ 4 红("实得 0s"、变量档期望 2026-12-31 实得 now);摘掉第五处 ⇒ 「必须带到期时间 Failed asserting that null is not null」。
  • 顺手去掉一处会漂移的断言(owner 口径:测试别写具体数字):SharedFlowParseTest 原 testAllFlowsCountIs15 每加一份共享夹具就得改一次,改成 $requiredFlows 点名必备夹具 + assertContains—— 新增不需要动它,某栈 flows 副本落后才红;负向对照点一个不存在的名报 contains 'no-such-flow.json' 证不恒真。
  • 跨栈一致性(同批八栈一起发,基准=boot2 内置版 ProcessTaskServiceImpl:213/386/524 三处写):普查发现写点其实是五处,第五处=串行会签推进出的下一位成员(boot2 的推进回调 createCountersignTask(:485,内含 :524 到期写)),各栈这一支普遍绕过本栈建单 helper 直建行,只看建单/回退两支会漏。另一处分叉在落地中被抓出来:回退新建的表达式该取 boot2 的 current=被回退掉的那个节点(:363 current = model.getNode(currentTask.getTaskName()) → :385 ((TaskModel)current).getExpireTime()),而不是落地行所属的 prev;java/php/csharp/rust/node/moon 取 current,go 与 python 头一轮取成了 prev,两栈当时的夹具只给一个节点配表达式 ⇒ 取错也全绿,是比对隔壁栈代码才发现。修完的判据改成双节点不同偏移(落地 1d ∧ 当前 3h ⇒ 断 ≈3h)+反向钉一档「当前未配 ⇒ 必须空」。

v1.3.15 — 2026-09-28 ​

  • 修复(issues/129 案 A,与 Java 1.8.32 同题):{"operator":""} 与缺键同档——空串(含全空白)视同未传,一并回落 demo 缺省 user1。六个缺省点(startAndExecute / instancePage / todoList / doneList / execute / ccList)统一走归一后的 operatorOf();此前内联 $args['operator'] ?? 'user1' 的 ?? 只兜 unset/null,而既有 operatorOf() 注释自称"对齐 Java"、实现对显式空串返回 ""。
  • 第二层在本栈不存在(取证过,未硬造):PdoProcessRepository::buildConditions() 逐条无条件拼 AND col = ? 并绑原值,InMemoryProcessRepository::matchCondition() 按值比对 ⇒ 空串被当真实归属值,于是本栈症状是"我的列表悄悄变 0 行"而不是那五栈的读全库(160 同时刻三档并排:user1=4 / ""=0 / __nobody__=0)。唯一的"空值 ⇒ 这条条件不加"通用放行在 PdoProcessExtRepository::buildSurrogateConditions(),只服务 processSurrogate/page 的 m_ 可选过滤(那里的 t.operator 是「授权人」业务列而非"我是谁")⇒ 按规范 06 §2.5「只收归属谓词」保持原样,由哨兵格钉住。
  • issues/114 边界:withdraw / transfer 的「operator 硬必填」(空串必须报 operator 必填)严禁接这个 helper,未动并有逐字断言。
  • 测试 T0(PHP 8.4,SKIP_MYSQL=1,sqlite::memory + InMemory 两后端各跑一遍):全套 387 tests / 2802 assertions OK(基线 380/2514,本版 +7 件),Skipped 44 与基线同数(全为 MySQL 路)。判据含"三档相等 + user1 档非空 + ≠ 全库 + ≠ 别人的档"、写侧两缺省点归一(空串不得被当成真实办理人)、绕过门面直喂归属空值的空页格与可选过滤哨兵格。
  • 变异对照:只回退 operatorOf ⇒ 3 红(空串档 0 行 ≠ user1 档),并排读数证四出口全红;往 buildConditions 注入五栈那条"空值即丢条件"⇒ 归属兜底件转红且读出全库行,证第二层有独立守格人。两文件按 sha256 还原。
  • 发版核验:Packagist mldong/jeeflow-php 列 v1.3.15,laravel 集成壳 composer update 解析到 v1.3.15(zipball reference 指向本仓修复 commit),CI Verify Release 绿。

v1.3.14 — 2026-09-28 ​

  • 修复(issues/124 遗留的一格 · 列表行变量原串出口):processTask/doneList、processInstance/detail.tasks[] 等仓储行出口仍带 variable 原串,门面侧上一轮只切了实例出口 ⇒ 本版把行侧 variable / instanceVariable 一并摘除,出口唯一保留 ext / instanceExt(空变量出 {})。这是 L2-26 门禁格(禁 variable/variables 出现在任何门面出口)在 php 上抓到的实际红。
  • 测试:PdoSqliteTaskRowExitTest 断言行上不含 variable 键且 ext 为对象;全量 T0 绿(当时基线 380/2514,Skipped 44 全为 MySQL 路)。Packagist 回拉 v1.3.14。

v1.3.13 — 2026-09-24 ​

  • 变更(issues/124 变量出口立法,对齐 Java v1.8.30 基准):JeeflowFacade 的 processInstance/detail 出口 variables 更名为 ext(getVariables()->toArray() ?: (object)[]——空变量出 {} 不出 []),variable 原串退出任务行出口;PHP 门面是仓储行的 pass-through,PdoProcessRepository / InMemoryProcessRepository 行键同步摘 variable。唯一出口 = ext(实例侧)+ instanceExt(任务行侧);持久层 variable 列不动。
  • 修复(demo)demo-slim 的 bin/demo-init.php CLI 路径此前未注册 UserProviderInterface(只有 HTTP 入口注册了),种子流程标题落工号——补 DemoUserProvider 注册后 25/25 实例标题为真名。
  • 测试 PdoSqliteTransferTest 断言改读 ext;全量 377 过 / 0 败 / 44 skip;Packagist 回拉 v1.3.13。

v1.3.12 — 2026-09-23 ​

  • 修复(委托判据取行顺序,对齐 Java 参考实现):单条裁决抽出为 SurrogateRule,PDO 仓与内存仓同形——各作用域 ORDER BY id DESC LIMIT 1 不带 enabled / 时间窗 / surrogate <> operator 谓词,读出后再判四条件(enabled 严格 1 / 被委托人非空且非本人 / 窗口覆盖判定时刻,起止 NULL = 该侧不限)。同层内判否不复活更旧那条;精确作用域判否(含池空)后仍要看全流程作用域的最新一条(SPI 契约注释同步写明回落规则)。
  • 修复(出口文案统一):退回上一步两格对外 msg 删 20010007: / 20010008: 码前缀(Domain/ProcessInstance.php 三处),改 Java 逐字中文文案;20010007 / 20010008 只留引擎内部,对外恒 code=99999999。断言补 assertStringNotContainsString('2001000', $msg) 反闸——只判「包含文案」对带前缀的旧文案恒绿。
  • 测试 php vendor/bin/phpunit --no-coverage ⇒ 377 例 / 2542 断言 / 0 失败(37 跳过为其他驱动分支);MysqlSmoke 真表套件实跑通过。新增用例 testNewestRowDecidesAndNeverFallsBackToOlder、testNewestInExactScopeFallsBackToGlobalRow、testNewestRowDecidesAndNeverFallsBackInBothRepos(双仓同答案)。
  • 变异对照 两仓兜底行取数改成 null ⇒ 6 例红(正向格 + 兜底格 + 双仓同答案 + 真落库 + 最新一条裁决 + MysqlSmoke),还原后 377/2542 全绿。
  • 实施留痕 本栈一度写成「精确作用域只要有记录就判否即止」并据此改判了三处既有期望,已按 Java 结论复原(PdoSqlite 的 opG 行、SurrogateAutoApplyTest 的兜底格、MysqlSmoke 的 leader 格)——跨层兜底是既有钉住的行为,不是本版新加。
  • 跨栈验证 13 个集成栈候选镜像门禁对拍:委托判据格 L2-17 全绿(13/13),13 栈逐格 0 分叉;L2-18 13 栈同形同错=门禁夹具支间未清场,非引擎缺陷。另:该栈宿主(Laravel 集成)此前恒判「不并」的观感实为应用时区偏差 8 小时伪装成判据缺失,框架侧配置改正后读数即与其余栈一致——排查委托不生效时先核时钟。

v1.3.11 — 2026-09-22 ​

09-22 夜发版轮(issues/120 时钟基座 + issues/121 P1/P2 血缘回退)PHP 侧代次;tag v1.3.11(11:11)。

  • 新增(121 P1):建单写 parentTaskId 与行级 isFirstTaskNode,门面读时行上值优先(4f4078e); 八个 PDO 夹具调用点补上这两个新参(e8ba873)。
  • 变更(121 P2):退回上一步改血缘版——复活血缘前驱行、参与者取该行办结人(7e696a6); submitType 3/6 口径拆开(dc32f99)。
  • 修复(issues/116 批次 D):委托条款 1.1 补 wf_process_define.name 回落 + 写侧脏值矩阵与逐路径用例(27719ae); 委托自动生效内置默认开启(a1b84b4)。
  • 测试基建(issues/118 §2.1):MySQL 版 PDO 三套件 DSN 改走 JEFFLOW_DB_* env,库不可达改显式 skip (此前是"恒 error 的套件=没有套件",签名级破坏能藏一整轮,c91bd53)。
  • 新增(issues/114/115):门面撤回鉴权 + processTask/transfer 转办落地(契约 778340a,1500df1)。
  • 发版核验:Packagist zipball 回拉核到;该仓 verify.yml 在 1.3.12 那轮才建 (首跑抓到 composer show | awk 在新列格式下掏出个冒号、判成"装到的是 :",改读 composer.lock 后转绿)。

v1.3.10 — 2026-09-07 ​

  • 修复(demo 层,引擎核心零改动)id 生成改 DbAwareIdGenerator——修「保留库升级」幂等隐患(480beb3,T003 夜班批):InMemoryIdGenerator 进程内自增固定从 1001 起,PHP 进程重启后 counter 归零,对有历史数据的 SQLite/MySQL 重新 deploy 必撞主键。demo 层构造时扫 8 业务表 MAX(id) 取全局最大起步,内存/MySQL 两仓储共用同一实例。
  • 同批(ac0b2c8,T003)demo 业务数据种子 driver:引擎真实启动 16 进行中 + 9 已完成 + 8 委托,八语言 demo 站覆盖矩阵对齐。
  • 验证:旧库(define 占 1001..1015)deploy 新 name code=0 id=1390 / demo-init 全跳过 / smoke 40 action 全过;公网全新库不受影响(本地复现路径)。

v1.3.9 — 2026-09-04 ​

  • 新增 stats 三 action(processInstance/stats/overview|trend|group):overview / trend / group 全 9 维度 + 内存聚合。
  • 修复 stats 契约对齐 A–E 验收(与 Java 参考实现逐字段一致):trend 桶枚举含 end 桶 + 时间过滤 end 含端(两线一致性)。
  • 事件收口 v1.3.8 落地事件机制后,随 laravel 基础仓 sys_message 列名对齐收口(receiver_user_id / sender_user_id,对齐种子库与其余六栈),CC_CREATE 抄送知会全链闭环。
  • 验证 gate24 24/24(L2-11 消息写路径绿)+ CC 五场景 + stats。

v1.3.8 — 2026-09-03 ​

  • 新增 引擎事件机制(方案 A):引擎侧 fire ProcessInstanceStart/End 等基础事件——PHP 无监听器体系,由集成层 WfMessageProcessEventListener 对动作后主动补发站内信(引擎只 fire、不保证消息落库)。

v1.3.7 — 2026-08-31 ​

  • 修复 design 读路径行键只认 camelCase:JeeflowFacade::designListByType / designDetail 读 PDO 行只取 displayName / isDeployed,而 PDO 持久化返回原列名 display_name / is_deployed → 未部署设计的 displayName 出口恒空、isDeployed 恒 0。改双读(向 designRowToMap 看齐),零出口键形变更。
  • 测试 T1 回归用例 testDesignReadPathPdoSnakeCaseKeys + 破坏性自证两发(红 → 红 → 复原绿,用例非恒真);全量 T0 287 tests / 1481 assertions 全绿 + T1 mysql-smoke 4/4;契约门禁出口键形 L2-10 入共享 runner(22 → 23)。
  • 集成验收 mldong-laravel-jeeflow bump → 通道 B 候选→生产 → laravel S13 转绿 → 生产 tag L0–L2 23/23。收口口径:本轮只动 PHP(单语言),收口只认 laravel 栈。

v1.3.6 — 2026-08-30 ​

  • 修复 删除/启停类 action 不认 {ids} 批量:改走统一助手 idListArgs({ids} 数组优先、单 {id} 兼容、两者皆缺 / 空数组 / 含非法值一律 99999999),processDefine/remove、processDesign/remove、processDefine/upAndDown 一并收敛——此前空值静默成功(DELETE ... WHERE id='' 删 0 行仍回 code=0)。
  • 测试 B 档入口批量形态矩阵(四 action × 四态,20→24 用例);自证已跑(legacy 实现下 16 组全静默成功 → 修复后全 99999999)。全量 T0 286 tests 全绿 + T1 4/4。
  • 与四语言 / Rust 同批。

v1.3.5 — 2026-08-24 ​

  • 修复 串行会签「一次建全」回归,改回逐个创建(对齐 Java 与 Go / Python / Node):节点入口只建 actors[0] 一个 DOING 任务,全量成员 + 计数器存首任务变量,每完成非最后一人建下一人、最后一人完成 merged。
  • 修复 CountersignHandler 串行分支判定 $csType === 2 → === CountersignType::SERIAL(SERIAL=1,原不可达分支本轮激活)。
  • 修复 JeeflowFacade.buildNodeProgress 会签成员清单改读任务变量 operatorList_{node}。
  • 全量 280 tests / 1300 assertions 全绿(PHP 8.4.24,REQUIRE_MYSQL 真库)。

v1.3.4 — 2026-08-23 ​

  • 语义修正 会签一票否决条件化 + merged 废弃残留任务(对齐 mldong 内置引擎 boot2/3):submitType=20 默认软拒绝;仅节点 countersignCompletionCondition=ONE_VOTE_VETO 时一票否决推进;merged 后废弃该节点剩余 DOING 任务(taskState=99)。
  • 修复 引擎缺口:getSurrogate 生效查询(时间窗 + enabled 过滤)+ highLight nodeProgress 会签成员进度。
  • 全量 277 tests / 1264 assertions 全绿。

v1.3.3 — 2026-08-20 ​

  • 修复 响应出口统一 id 字符串化:JeeflowFacade::flow() 对 data 递归 stringifyIds()——单记录端点此前 19 位雪花 id 以 JSON 数字下发,前端 float64 丢精度致 designer 保存静默 no-op(L3 S8a 偶发根因)。对齐 Java / Go / Node。
  • 修复 嵌套 his 快照列表的 id / process_design_id 同步字符串化;JeeflowFacadeIssue61Test 匿名类补接口方法(预存 PHP fatal)。
  • 全量 242 tests / 919 assertions 全绿;Laravel L3 E2E 14 过 / 1 skip / 0 失败。

v1.3.2 — 2026-08-19 ​

  • 修复 pageCcInstances 补 ext / instanceExt 字段(SELECT 增 instance_variable 解析输出),修复 L3 E2E S6 抄送列表行渲染失败。

v1.3.1 — 2026-08-19 ​

  • 修复 pageCcInstances 补 JOIN wf_process_instance / wf_process_define,新增 displayName / processDefineName / version / operator 字段(此前抄送列表前端定义名称/版本列空白)。

v1.3.0 — 2026-08-19 ​

  • 修复 TaskNodeParser performType/countersignType 改用枚举 from() 替代 (int) 强转,正确处理字符串值(此前会签场景走错分支)。
  • 新增 AssignmentHandler SPI 机制(对齐 Java CreateTaskHandler):AssignmentHandlerInterface + 注册表 + 内置 FormFieldAssigneeHandler / ApplicantDeptLeaderAssignmentHandler;CreateTaskHandler::resolveActors() 新增 actors 为空时 handler 分支。
  • 扩展 OrgUserProviderInterface 新增 findDeptLeaders() / findDeptMainLeaders()。

v1.2.1 — 2026-08-18 ​

  • 修复 pageInstances 结果补 JOIN wf_process_define,新增 displayName / version / processDefineName 等字段(前端「我发起的」列不再空白)。

v1.2.0 — 2026-08-18 ​

  • 新增 FlowUtil 用户信息注入 addUserInfoToArgs() + 自动标题 addAutoGenTitle();EnumDictRegistry 元数据模块(7 内置字典)+ HandlerRegistry 7 内置 Handler;枚举 label() 方法 + CountersignType 枚举类。
  • 测试 新增 22 个单元测试,全量 241 tests / 911 assertions。

v1.1.3 — 2026-08-17 ​

  • 修复 空 Map 序列化对齐:variable / ext / taskFormData / nodeProgress 等空值统一 (object)[](JSON {}),对齐 Java / Go / Python / Node;listByType 的 processDesignId 转 string。

v1.1.2 — 2026-08-15 ​

  • 修复 PDO 分页 LIMIT ? 内联为整数;PDO hydrate 主键 int → string,setTaskId 不再类型失败。
  • 新增 persist 拦截器 / 写侧:ARCHIVE / SYNC 落业务表;T1 冒烟 M1–M4 并入 changelog。

v1.1.1 — 2026-08-13 ​

  • 修复 processTask/detail 的 taskModel 补全 ext / form 字段。
  • 修复 processDesign/page 时间格式对齐 yyyy-MM-dd HH:mm:ss。

v1.1.0 — 2026-08-12 ​

  • 新增 processTask/candidatePage:模型候选双源 + 用户搜索回落。
  • 新增 processInstance/bizData:业务数据读侧回显。
  • 新增 SPI:UserSearchProviderInterface、OrgUserProviderInterface。

v1.0.0 — 2026-08-11 ​

  • 新增 引擎核心(packages/core):ProcessInstance 聚合根 + 状态机 + 6 SPI + 7 Handler,行为对齐 Java。
  • 新增 持久化(packages/repository-pdo):MySQL 八表 + InMemory + SQLite 默认存储。
  • 新增 统一门面(packages/web-contract):JeeflowFacade 40 action;PSR adapter(packages/web-psr)+ 参考 demo(demo-slim,Slim 4)。

jeeflow · 轻量级多语言工作流引擎