Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
16afa01
feat(workflow): add durable pull request delivery
nateEc Oct 23, 2026
6056c15
fix(workflow): retain every enclosing delivery timeout
nateEc Oct 23, 2026
f6490bc
fix(workflow): recheck cancellation before opening review requests
nateEc Oct 23, 2026
4e732bc
Merge branch 'main' into feat/1090-workflow-pr-delivery
SaulMoro Oct 24, 2026
7e6bef5
refactor(workflow): derive step status lists from one source
SaulMoro Oct 24, 2026
cd1d638
feat(workflow): refuse deliver: pr where nothing writes a branch
SaulMoro Oct 24, 2026
d904910
feat(workflow): deliver a driver-reported pull request from workflow …
SaulMoro Oct 24, 2026
7cad046
feat(workflow): name a dropped pull request URL without echoing it
SaulMoro Oct 24, 2026
455b638
feat(workflow): refuse to deliver a branch that changes protected paths
SaulMoro Oct 24, 2026
2e4240e
fix(workflow): keep delivered pull requests as run receipts
SaulMoro Oct 24, 2026
e7871bb
feat(workflow): open the pull request through the origin's provider
SaulMoro Oct 24, 2026
5db2f04
fix(workflow): keep a reported pull request on the origin host only w…
SaulMoro Oct 24, 2026
98ebc9e
fix(workflow): hand over the branch a copy started from
SaulMoro Oct 24, 2026
f50d019
feat(workflow): open a pull request into the delivered branch it grew…
SaulMoro Oct 24, 2026
c88e9c5
fix(workflow): start the next for_each item while an earlier one deli…
SaulMoro Oct 24, 2026
1c70b30
feat(workflow): record a pull request a stopped delivery left open
SaulMoro Oct 24, 2026
1bc6cb9
test(workflow): hand over a run while a step delivers its pull request
SaulMoro Oct 24, 2026
4eae92b
feat(workflow): judge the agent pass of a step that delivers
SaulMoro Oct 24, 2026
5dcf97f
feat(providers): look up the open GitLab merge request of a delivered…
SaulMoro Oct 24, 2026
3e4246c
feat(tgit): find the open merge request of a delivered branch
SaulMoro Oct 24, 2026
ff56180
feat(gitcode): find the open pull request of a delivered branch
SaulMoro Oct 24, 2026
64971ab
test(cnb): pin that a CNB origin delivers over git alone
SaulMoro Oct 24, 2026
5f8adfe
fix(workflow): refuse an open pull request a lookup finds on another …
SaulMoro Oct 24, 2026
7268591
fix(workflow): record the URL a host lists for a pull request it just…
SaulMoro Oct 24, 2026
7a799be
test(workflow): run the delivery scenarios against each kind of drive…
SaulMoro Oct 24, 2026
2ed026a
test(workflow): run the local driver while another process delivers
SaulMoro Oct 24, 2026
b46f190
docs(workflow): document pull request delivery and run the CI recipe …
SaulMoro Oct 24, 2026
176988c
test(workflow): pin that a stopped create is only looked up when the …
SaulMoro Oct 24, 2026
77e7f7f
test(init): mock the TGit open merge request lookup
SaulMoro Oct 24, 2026
693a265
Merge branch 'main' into feat/1090-workflow-pr-delivery
SaulMoro Oct 24, 2026
1caecba
fix(workflow): deliver a branch only while origin holds the commit th…
SaulMoro Oct 24, 2026
cd2d09d
fix(workflow): keep the requests a delivery asked for on the run, not…
SaulMoro Oct 24, 2026
3004253
fix(workflow): record no URL after a create that the origin host chec…
SaulMoro Oct 24, 2026
8363b90
fix(workflow): keep what the agent settled when its delivery is cance…
SaulMoro Oct 24, 2026
52500e0
fix(workflow): leave a step delivering when the run lock is busy at t…
SaulMoro Oct 24, 2026
7374ee4
fix(workflow): name a reported pull request URL that no delivery uses…
SaulMoro Oct 24, 2026
0c98482
fix(workflow): refuse deliver: pr on a workflow step whose workflow n…
SaulMoro Oct 24, 2026
1247f9e
docs(workflow): say when a run another machine took over can open a s…
SaulMoro Oct 24, 2026
67e8804
fix(github): look up an open pull request without blocking the process
SaulMoro Oct 24, 2026
a467b0b
fix(workflow): read changes.pr_url sent without the branch facts
SaulMoro Oct 24, 2026
90363fb
docs(workflow): say where a condition that stops a run must live for …
SaulMoro Oct 24, 2026
3fa365f
fix(workflow): keep cancelled writes out of automatic delivery
SaulMoro Oct 24, 2026
9c65c39
fix(workflow): deliver later branch tips recorded by reports
SaulMoro Oct 24, 2026
69a75d3
Revert "fix(workflow): read changes.pr_url sent without the branch fa…
SaulMoro Oct 24, 2026
05e001a
fix(workflow): bound unresolved create reconciliation across drains
SaulMoro Oct 24, 2026
c115b94
fix(workflow): keep unconfirmed creates pending for canonical lookup
SaulMoro Oct 24, 2026
50e3554
fix(github): settle lookup independently of launcher pipe closure
SaulMoro Oct 24, 2026
a52b6c9
fix(workflow): distinguish missing branches without credential prompts
SaulMoro Oct 24, 2026
14c62c7
fix(workflow): require an acting step to qualify delivery writes
SaulMoro Oct 24, 2026
c5ce069
refactor(workflow): keep delivery state and schemas in one ledger
SaulMoro Oct 24, 2026
3ad890f
style(workflow): remove trailing blank line from delivery ledger
SaulMoro Oct 24, 2026
bc34906
fix(workflow): check the selected delivery tip against the run base
SaulMoro Oct 24, 2026
743f4d5
fix(workflow): name the recorded head and wait for an ahead branch
SaulMoro Oct 24, 2026
da1def3
fix(workflow): blame a later commit for its own protected change
SaulMoro Oct 24, 2026
0b476cc
fix(workflow): require a recorded tip to contain the step's head
SaulMoro Oct 24, 2026
3335665
fix(workflow): read the delivery tip with the shared non-interactive …
SaulMoro Oct 24, 2026
e5da6a0
fix(workflow): count a retried create's lookups from zero
SaulMoro Oct 24, 2026
ad25dc8
refactor(workflow): keep delivery schemas in a leaf module
SaulMoro Oct 24, 2026
504b954
fix(workflow): treat an empty lookup after a create as unconfirmed
SaulMoro Oct 24, 2026
ff6a7f6
docs(workflow): name deliverPr as the subject of the tip diff
SaulMoro Oct 24, 2026
e12d9b9
feat(workflow): add durable pull request delivery
nateEc Oct 23, 2026
16f84d0
fix(workflow): retain every enclosing delivery timeout
nateEc Oct 23, 2026
e6274b8
fix(workflow): recheck cancellation before opening review requests
nateEc Oct 23, 2026
3e94b50
fix(workflow): read git's own exit code, so an error is not "not an a…
SaulMoro Oct 24, 2026
8c64d81
Merge branch 'main' into feat/1090-workflow-pr-delivery
SaulMoro Oct 24, 2026
d609e16
fix(workflow): 在跨机器交接时保留待交付状态
nateEc Oct 24, 2026
efdaf68
Merge the rebased contributor branch, keeping the redesigned delivery
SaulMoro Oct 24, 2026
e8383b4
fix(workflow): read origin's tip again before opening a pull request
SaulMoro Oct 24, 2026
70573e6
fix(workflow): keep waiting for an ahead tip while a writer of the br…
SaulMoro Oct 24, 2026
a97524f
fix(workflow): take a found pull request only once origin's branch is…
SaulMoro Oct 24, 2026
64e1b8d
Merge branch 'main' into feat/1090-workflow-pr-delivery
SaulMoro Oct 24, 2026
ae4c9f0
fix(workflow): open no pull request that leaves out work a step insid…
SaulMoro Oct 24, 2026
d043804
fix(workflow): drop a reported URL on the origin host that cannot be …
SaulMoro Oct 24, 2026
75c6152
fix(workflow): name remedies a protected later commit and an ahead ti…
SaulMoro Oct 24, 2026
36f82cc
fix(workflow): fail an ahead tip once no report of it can come
SaulMoro Oct 24, 2026
354fced
fix(workflow): deliver nothing while another writer of the branch is …
SaulMoro Oct 24, 2026
491d8ce
fix(workflow): bound the fetch delivery runs, and keep it from prompting
SaulMoro Oct 24, 2026
f16c130
fix(workflow): pass over a delivery while a writer of its branch is l…
SaulMoro Oct 24, 2026
c46ebb9
Merge origin/main (#1303, #1301, #1344) into pr-1306
SaulMoro Oct 24, 2026
58eab0e
test(workflow): pin that a timeout stops delivery before anything opens
SaulMoro Oct 24, 2026
ab44ccf
fix(workflow): fail a workflow step that would deliver nothing and lo…
SaulMoro Oct 24, 2026
a8f6b6b
fix(workflow): take no found pull request while its branch is unchecked
SaulMoro Oct 24, 2026
ff5de03
refactor(workflow): name the fault fields of left-out child work
SaulMoro Oct 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions docs/dev/workflow-engine.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/guide/workflow-advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -715,11 +715,11 @@ teamai workflow cancel <run> [step]
teamai workflow resume <run> --tools default=claude
```

`retry` accepts a leased, failed, or cancelled step, a refused approve with an answer, or an answered choose. Retry a HITL request to change its answer; its old answer stays in pass history. It frees an old lease and starts a new pass at a new revision. The local driver stops a command it was running and starts the new pass only after that command has exited. It resets the steps that depend on or read that step, including loop waits and item `after` dependencies. A HITL request among them that waits, or was answered and has not run, is asked again at a new pass. It reopens settled enclosing workflows, items, fan-out steps, and the run. If the reopened run is still running, the result includes a `resume` command. Run it to continue locally, or let your driver poll `next`. Unanswered skips in each affected container are re-derived; manual cancellations outside it stay cancelled. An independent standing end or break prevents retry.
`retry` accepts a leased, failed, or cancelled step, a refused approve with an answer, or an answered choose. Retry a HITL request to change its answer; its old answer stays in pass history. It frees an old lease and starts a new pass at a new revision. The local driver stops a command it was running and starts the new pass only after that command has exited. It resets the steps that depend on or read that step, including loop waits and item `after` dependencies. A HITL request among them that waits, or was answered and has not run, is asked again at a new pass. It reopens settled enclosing workflows, items, fan-out steps, and the run. A step whose pull request delivery failed keeps its pass, and only its delivery runs again. If the reopened run is still running, the result includes a `resume` command. Run it to continue locally, or let your driver poll `next`. Unanswered skips in each affected container are re-derived; manual cancellations outside it stay cancelled. An independent standing end or break prevents retry.

History stays in `passes` and the archive, so `length(steps.x.passes)` counts failed attempts too. Retrying a loop owner resets its iteration count. Retrying another step in its range keeps the owner's count. Retry keeps the top-level workflow's round count, so retry in its exhausted final round can fail `loop_exhausted` again.

A single-step `cancel` stops pending, waiting, leased, or running work. Its open descendants stop too. Cancelled steps count as stopped, so dependents skip unless an `if` reads their outcome for recovery. The run normally fails. A whole-run cancel ends immediately with run outcome `cancelled`, without starting another loop round. Cancel does not bump the revision. A late report returns `lease_cancelled`; `next.cancelled` tells drivers which tools to stop.
A single-step `cancel` stops pending, waiting, leased, running, or delivering work. Its open descendants stop too. Cancelled steps count as stopped, so dependents skip unless an `if` reads their outcome for recovery. The run normally fails. A whole-run cancel ends immediately with run outcome `cancelled`, without starting another loop round. Cancel does not bump the revision. A late report returns `lease_cancelled`; `next.cancelled` tells drivers which tools to stop.

`resume` drives the run locally after a retry, response, Ctrl-C, or closed terminal. `workflow start --driver local` prints the run id on stderr when the run starts, with the `resume` command that continues it. It uses this machine's open local lease workspace first, then the workspace of the latest driver that called `next` when that driver was local on this machine, then the current directory. Resuming after a retry from a subdirectory therefore keeps the original local workspace. Only one local driver can drive a run at a time. A second resume returns `driver_running` with the owning process id; stop that driver or wait. Locks from dead processes are reclaimed automatically. A settled run returns `done`. Failed and cancelled local runs exit 1; successful control commands exit 0 even when their answer describes a failed or cancelled run.

Expand Down
67 changes: 65 additions & 2 deletions docs/guide/workflow.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/guide/zh-CN/workflow-advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -715,11 +715,11 @@ teamai workflow cancel <run> [step]
teamai workflow resume <run> --tools default=claude
```

`retry` 接受 leased、failed 或 cancelled 步骤,也接受已回答并拒绝的 approve 和已回答的 choose。重试 HITL 请求可以更改答案,旧答案保留在 pass 历史中。它释放旧租约,以新修订号启动新 pass(本地驱动会停止正在运行的命令,并等它退出后才启动新 pass),重置依赖或读取该步骤的后续步骤,包括循环等待和 item 的 after 依赖(其中正在等待、或已回答但尚未运行的 HITL 请求会在新 pass 中重新询问),并重新打开已结算的外层工作流、item、fan-out 步骤和运行。如果重新打开后运行仍在进行,返回结果会包含 `resume` 命令。执行该命令继续本地运行,或让驱动轮询 `next`。每个受影响容器中未回答的跳过步骤会重新计算;范围外手动取消的步骤保持取消。无关步骤已到达的有效结局或 break 会阻止重试。
`retry` 接受 leased、failed 或 cancelled 步骤,也接受已回答并拒绝的 approve 和已回答的 choose。重试 HITL 请求可以更改答案,旧答案保留在 pass 历史中。它释放旧租约,以新修订号启动新 pass(本地驱动会停止正在运行的命令,并等它退出后才启动新 pass),重置依赖或读取该步骤的后续步骤,包括循环等待和 item 的 after 依赖(其中正在等待、或已回答但尚未运行的 HITL 请求会在新 pass 中重新询问),并重新打开已结算的外层工作流、item、fan-out 步骤和运行。交付 pull request 失败的步骤保留原来的 pass,只重新运行交付。如果重新打开后运行仍在进行,返回结果会包含 `resume` 命令。执行该命令继续本地运行,或让驱动轮询 `next`。每个受影响容器中未回答的跳过步骤会重新计算;范围外手动取消的步骤保持取消。无关步骤已到达的有效结局或 break 会阻止重试。

历史保留在 passes 和 archive 中,因此 `length(steps.x.passes)` 也统计失败尝试。重试循环所有者会重置其迭代数;重试范围内的其他步骤则保留所有者的计数。重试保留顶层工作流的 round,耗尽最后一轮后重试仍可能再次 `loop_exhausted`。

指定步骤的 cancel 停止 pending、waiting、leased 或 running 工作,同时停止尚未结束的后代。cancelled 属于 stopped,因此依赖步骤会跳过,除非其 if 读取取消结果来恢复;运行通常失败。取消整个运行立即以 `cancelled` 结束,不启动下一轮。cancel 不增加修订号。迟到的报告返回 `lease_cancelled`,`next.cancelled` 告诉驱动停止哪些工具。
指定步骤的 cancel 停止 pending、waiting、leased、running 或 delivering 工作,同时停止尚未结束的后代。cancelled 属于 stopped,因此依赖步骤会跳过,除非其 if 读取取消结果来恢复;运行通常失败。取消整个运行立即以 `cancelled` 结束,不启动下一轮。cancel 不增加修订号。迟到的报告返回 `lease_cancelled`,`next.cancelled` 告诉驱动停止哪些工具。

在重试、回答、Ctrl-C 或关闭终端后,用 resume 继续本地运行。`workflow start --driver local` 在运行开始时就把运行 id 和继续它的 `resume` 命令输出到 stderr。它优先使用本机未结本地租约的工作目录,其次使用最近调用 `next` 的驱动工作目录(该驱动必须是本机本地驱动),最后使用当前目录。因此重试后即使从子目录继续,也会保留原来的本地工作目录。每个运行同时只能有一个本地驱动。重复 resume 返回 driver_running 和持有者进程号,请停止该驱动或等待;死进程留下的锁会自动回收。已结算运行返回 done。本地运行以 failed 或 cancelled 结束时退出码为 1;控制命令成功时退出码为 0,即使返回的运行状态为 failed 或 cancelled。

Expand Down
Loading
Loading