← 返回列表
未验证
一个面向 DeepSeek Harness…
尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/8/24 · 已提供中文文档
DeepSeek Harness 的 Workflow-net 运行时:资源感知并发、原生循环与扇出、在计划变为持久化之前进行静态健全性检查,以及对其自身事件日志进行流程挖掘。
综合分
28.2
GitHub 分
28.2
用户评分
—
★ Stars
1
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add yxie2/dsh-petrinet该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/19(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-agent@deepseek-ai/dsh-attachment@deepseek-ai/dsh-commands@deepseek-ai/dsh-invariants@deepseek-ai/dsh-llm@deepseek-ai/dsh-scope@deepseek-ai/dsh-session@deepseek-ai/dsh-session-projection@deepseek-ai/dsh-subagent@deepseek-ai/dsh-system-prompt@deepseek-ai/dsh-timeout用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
dsh-petrinet
一个面向 DeepSeek Harness 的工作流网运行时。它将长周期计划建模为状态——令牌驻留在库所中,变迁消耗并产生它们——这赋予了它三个特性:
1. 资源感知的并发。 一个信号量、一个互斥锁、一个 API 配额、一条“同一时间只允许一个 agent 触碰仓库”的规则——全都只需一次声明,由驱动其他一切的同一触发规则来强制执行。
2. 原生循环与运行时扇出。 重试直到成功、轮询直到就绪,以及“对你发现的每个条目各运行一次”都是普通结构。
3. 在计划变为持久化之前进行静态健全性检查。 一个可能死锁的计划会在提交时被拒绝,并附带一个具体的反例——在任何工作开始之前。
除此之外,它还会挖掘自身的执行日志,以提出有证据支撑的计划改进建议。
dsh plugin add @yxie2/petrinet
初次接触?阅读简介——从问题的形态到运行时对此的应对,阐述该设计背后的理由。本 README 是参考文档。中文读者请看中文简介。
工作流网建模什么
库所持有令牌。变迁从其输入库所消耗令牌,并将其产生到输出库所中。一个变迁只有在每个输入库所都持有足够令牌时才能触发。这一条规则承载了很多东西:
| | 如何表达 |
|---|---|
| 并发限制 | 一个持有 k 个令牌的库所就是一个 k 路信号量 |
| 循环 | 结构中的一个环 |
| 运行时扇出宽度 | 一个库所中的 n 个令牌 = n 个并行工作项 |
| AND 汇合 vs XOR 汇合 | 结构上截然不同 |
而且因为它是 Petri 网,六十年的分析成果随之而来:可达性、有界性、守恒律,以及一个可判定的健全性概念。
健全性门禁
这是值得整个设计的特性。
每个计划在进入持久化日志之前都会被静态分析。在探索预算之内,判定结果是证明,而非启发式——van der Aalst 的三个条件在具体枚举出的可达图上进行检查:
1. 可完成选项——每个可达状态仍能到达终点。
2. 正确完成——到达终点意味着没有任何东西被遗留。
3. 无死变迁——每一步都在某处可达。
这里有一个看起来完全合理的计划。两个分支,每个都需要两把锁:
{
"resources": [{ "id": "A", "capacity": 1 }, { "id": "B", "capacity": 1 }],
"flow": { "parallel": [
{ "guard": { "resource": "A", "body": { "guard": { "resource": "B", "body": { "task": { "id": "w1" } } } } } },
{ "guard": { "resource": "B", "body": { "guard": { "resource": "A", "body": { "task": { "id": "w2" } } } } } }
] }
}
petri_plan 会拒绝它:
PETRI_UNSOUND_PLAN: net is unsound: 2 deadlock marking(s) reachable;
1 reachable marking(s) can no longer reach the final marking
而 petri_analyze 会返回它本应死锁的状态:
{ "deadlockExample": { "p.guard.g1.body": 1, "p.guard.g3.body": 1 } }
两个分支各持有一把锁,彼此等待对方。经典的锁反转,在花费任何一个 token 之前就被捕获。放宽任一资源,或按一致的顺序获取,同一个计划就能验证为 SOUND。
当答案未知时,它会如实说明。 超过探索上限后,判定结果是 UNKNOWN,绝不会是乐观的 SOUND。通过具体反例发现的违规即使在有上限的情况下也依然确定,因为死锁标记无论还有什么未被探索,都没有可触发的变迁。
模型编写结构,而非弧
模型擅长嵌套的任务结构,却不擅长输出库所、变迁和弧权重。因此 Petri 网是中间表示,绝不是表层语法。模型编写一个小型模式 DSL:
{
"resources": [{ "id": "repo_lock", "capacity": 1 }, { "id": "ci_slots", "capacity": 3 }],
"flow": { "seq": [
{ "task": { "id": "survey", "name": "Survey the codebase" } },
{ "foreach": { "id": "each_pkg", "over": "packages needing migration",
"body": { "guard": { "resource": "ci_slots",
"body": { "task": { "id": "migrate" } } } } } },
{ "guard": { "resource": "repo_lock",
"body": { "loop": { "id": "green", "maxIterations": 5,
"body": { "task": { "id": "fix_tests" } } } } } }
] }
}
| 节点 | 含义 |
|---|---|
| task | 一个真实工作单元,分派给子代理 |
| seq | 按顺序运行 |
| parallel | AND 分支,并发运行,全部完成后汇合 |
| choice | XOR 分支,恰好选择一条分支 |
| loop | 重复直到走退出分支(由 maxIterations 限定) |
| foreach | 在运行时发现 n 个条目,对每个条目运行一次主体,然后收集 |
| guard | 在主体持续期间持有一个信号量 |
每个模式都降级为一个恰好有一个入口库所和一个出口库所的片段,并且此类片段的组合在工作流网形态下是封闭的。因此,控制流模式在构造上就是可靠的。 分析器的存在是为了捕获组合无法保证的东西:资源引发的死锁——而这正是真实的长时运行计划实际失败的地方。
Token 仅在验证时移动
每次触发都是两阶段的,而这两个阶段由裁决分隔:
claim 在租约下消耗输入 token (保留,而非销毁)
|
execute 分派一个子代理
|
report 工作者关于环境的声明 产生输出 token
+-- failed -> 归还消耗的 token,消耗一次尝试
一个自信但错误的子代理无法推进网络。没有任何东西能自我认证。
标记是派生的,从不存储——重新折叠会话日志即可重建精确的运行时状态,因此崩溃恢复、重放和时间旅行调试都是免费的。一个静默死亡的 worker 会使其租约过期,其令牌被归还,其转换被重新启用。
并发来自网络
驱动器不进行调度。它触发网络所启用的一切,而网络的资源位置决定了一次可以发生多少:
resources: [{ id: 'slots', capacity: 2 }]
这就是双向并发上限的完整实现。来自测试套件:
capacity 1 -> peak concurrency 1
capacity 2 -> peak concurrency 2
capacity 3 -> peak concurrency 3
驱动器上的 maxConcurrency 是在此之上的第二层、更粗粒度的上限——一个安全限制,而非机制本身。
从日志中学习
事件流无需任何额外插桩,就是一个流程挖掘事件日志:案例 id(网络修订版)、活动(转换)、顺序、结果。这是一个领域的规范输入,而该领域的规范输出是 Petri 网。这个循环自我闭合。
petri_insights 报告两件事:
一致性。 候选计划与实际发生情况之间的令牌重放适应度。这就是如何依据历史而非模型自身的乐观来评判所提议的修复——一个得分比它所替代的计划更差的修复不是修复。
适配。 具体数字,每个都由一次计数的观察作为支撑:
[
{ "kind": "maxAttempts", "target": "t.flaky", "current": 3, "suggested": 4,
"rationale": "hit its budget of 3 yet committed elsewhere in history (worst streak 3); the failures are transient" },
{ "kind": "resourceCapacity", "target": "ci_slots", "current": 3, "suggested": 4,
"rationale": "drained to zero while 18 further acquisition(s) were otherwise ready; widening it raises real concurrency" }
]
alphaMine 还会从观察到的行为中重新发现一个网络,因此你可以将你计划的内容与实际发生的情况进行对比。
自我修复,从最廉价开始
当一个网络死亡时,驱动器分层修复它:
1. adaptive——免费。从会话自身的历史中推导出参数变更。不调用模型,每个变更都由一次观察作为支撑。
2. llm——模型编写一个替代的工作流规范,它经过与人类路径相同的编译器,并继承相同的构造即正确的模式。它被逐字地交给分析报告,包括具体的死锁标记,因为“这是你陷入的确切状态”远比“你的计划失败了”更具可操作性。
两个提议在提交前都要通过健全性门禁。 一个提出死锁的模型会得到拒绝,而不是一个卡住的网络。这道门禁正是将这与无界自我修改区分开来的东西。
结构变更绝不会从挖掘中自动应用——死锁转移的观察结果只会被报告,绝不会被据以行动。放宽预算是可逆的算术;重写计划则是一项决策。
诚实的局限,事先说明:
- 重试探测是有上限的(RETRY_PROBE_CEILING)。一个从未成功过的步骤只会再获得一次尝试机会,仅此一次——超过之后,更多的耐心并不是答案,代码在其输出的理由中也是这样说的。
- alpha 算法无法看到长度为 1 或 2 的循环、重复活动或不可见的路由步骤。请把低适应度分数当作一个问题,而不是一个判决。
工具
| 工具 | 用途 |
|---|---|
| petri_create | 为长周期目标打开一个网 |
| petri_analyze | 编译并检查候选计划,而不提交它 |
| petri_plan | 将计划提交为下一个修订版(CAS;若不健全则拒绝) |
| petri_status | 标记、已启用的转移、选择点、每一次触发 |
| petri_insights | 针对历史的一致性 + 有证据支持的适配 |
| petri_cancel | 中止当前网 |
外加一个 /petri 斜杠命令(status / analyze / cancel / )。
petri_analyze 是值得鼓励使用的那个:它把死锁从四十小时的损失变成规划阶段的一次免费修正。
配置
默认值不产生任何成本——确定性选择,无需修复:
- id: petri-driver
name: '@yxie2/petrinet/driver-host'
config:
decider: llm # deterministic (default) | llm — only consulted at real choice points
repair: both # off (default) | adaptive | llm | both
maxConcurrency: 4
approveRepairs: false
repair: adaptive 同样免费——它读取的是历史,而不是模型——所以它是首先值得开启的东西。
llm 决策器只在转移真正竞争相同令牌的地方被咨询。无竞争的进展和控制转移完全不产生模型调用。
架构
compile.ts workflow DSL -> workflow net (sound by construction)
soundness.ts structural | invariants | reachability (the gate)
net.ts the firing rule: enabling, conflict, marking algebra
fold.ts events -> state (the marking is derived, never stored)
validate.ts admissibility, incl. the soundness gate on every revision
mining.ts traces, alpha algorithm, conformance, adaptations
|
+-- zero runtime dependencies; runs under node --experimental-strip-types
|
driver.ts the concurrent firing loop
service.ts ctx.petri — event-sourced, CAS revisions
tools.ts / trigger.ts / driver-host.ts / invariant.ts / projection.ts
整个引擎——语义、降级、分析、折叠、挖掘——都刻意不依赖任何 harness。它的测试套件无需安装,也无需构建:
node --experimental-strip-types tests/net.test.mjs
那里的回归是数学上的回归,而不是集成上的回归。
npm test # all suites
npm run build # typecheck + emit lib/
先前技术
这是应用性工作,而非凭空发明的理论。它依赖于:
- W.M.P. van der Aalst,The Application of Petri Nets to Workflow Management(1998)——工作流网与健全性。
- van der Aalst、ter Hofstede 等,Workflow Patterns(2003)以及 YAWL——该 DSL 所实现的模式集合。
- van der Aalst,Process Mining——alpha 算法与令牌重放一致性。
- Rozinat & van der Aalst,Conformance Checking of Processes Based on Monitoring Real Behavior(2008)——适应度指标。
- dsh-mission——本包全盘采纳的原则(智能体提议,环境裁定,运行时提交),以及其针对持久化规划状态所采用的事件溯源、比较并交换方法。两者可并排安装。
许可证
MIT扫码进群