Appearance
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归一(字段集逐字对齐 javaProcessDesignHis), 微秒尾经 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空档{}无实例变量回落。 - 降级档说明:表达式求值复用引擎同一个
ExpressionEvaluatorSPI 口,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下实测报 1366HY000——旧副本没有那 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::updateCCStatusoperator 归一、两仓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 环境的正常档); T1REQUIRE_MYSQL=1433 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 MysqlSmokeOK (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),CIVerify 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.phpCLI 路径此前未注册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-1813 栈同形同错=门禁夹具支间未清场,非引擎缺陷。另:该栈宿主(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);submitType3/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新 namecode=0id=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 全绿 + T1mysql-smoke4/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 过滤)+highLightnodeProgress 会签成员进度。 - 全量 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补 JOINwf_process_instance/wf_process_define,新增displayName/processDefineName/version/operator字段(此前抄送列表前端定义名称/版本列空白)。
v1.3.0 — 2026-08-19
- 修复
TaskNodeParserperformType/countersignType 改用枚举from()替代(int)强转,正确处理字符串值(此前会签场景走错分支)。 - 新增 AssignmentHandler SPI 机制(对齐 Java
CreateTaskHandler):AssignmentHandlerInterface+ 注册表 + 内置FormFieldAssigneeHandler/ApplicantDeptLeaderAssignmentHandler;CreateTaskHandler::resolveActors()新增 actors 为空时 handler 分支。 - 扩展
OrgUserProviderInterface新增findDeptLeaders()/findDeptMainLeaders()。
v1.2.1 — 2026-08-18
- 修复
pageInstances结果补 JOINwf_process_define,新增displayName/version/processDefineName等字段(前端「我发起的」列不再空白)。
v1.2.0 — 2026-08-18
- 新增 FlowUtil 用户信息注入
addUserInfoToArgs()+ 自动标题addAutoGenTitle();EnumDictRegistry元数据模块(7 内置字典)+HandlerRegistry7 内置 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):JeeflowFacade40 action;PSR adapter(packages/web-psr)+ 参考 demo(demo-slim,Slim 4)。