关于 prune
prune 是用于批量清理过期未终止工作流的 Exarchos 技能。它会先预览候选项并检查保护条件,再等待确认;清理事件与普通取消事件分别记录。
主要功能
- 01预览待清理候选项
- 02检查开放 PR 和分支活动
- 03明确选择继续、中止或强制执行
- 04批量取消并记录审计事件
适用场景
- 01清理前检查不活跃工作流
- 02批量移除流水线中的过期工作流
- 03查看保护条件跳过项后强制清理
MCP 相关
通过 Exarchos MCP 服务的 `prune_stale_workflows` 编排操作筛选并清理工作流。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ lvlup-sw/ exarchos --skill prune安装后在 Claude Code 中输入/prune确认已加载。
附带文件references/safeguards.md
详细介绍
清理工作流技能
VCS 提供方
此技能在内部使用 VCS 操作作为安全防护(检测是否有已打开的 PR)。
orchestrate 处理程序会自动管理 VCS 提供方的分派。
无需使用 gh/glab/az 命令 — MCP 服务会处理提供方分派。
概述
批量取消管道中累积的过期非终态工作流。此技能封装了 prune_stale_workflows orchestrate 操作,并提供交互式的“先试运行、再确认”体验,确保用户始终能在任何状态变更之前查看候选项。
清理是一项维护操作,而非工作流阶段。除了底层取消路径发出的标准 workflow.cancelled 事件外,它还会生成 workflow.pruned 事件,让下游视图能够区分用户主动取消和批量清理。
触发条件
在以下情况激活此技能:
- 用户运行
prune命令 - 用户说“清理工作流”“清理过期工作流”或“清理管道”
exarchos:exarchos_view({ action: "pipeline", scope: "all" })显示有许多用户想要批量清除的非活动工作流。由于默认视图限定于仓库范围,会隐藏清理功能旨在清除的 legacy 条目(在记录仓库身份之前启动的工作流),因此清理功能使用scope: "all"查看候选项。限定于仓库范围的查看会漏掉它要清理的对象。
前提条件
- exarchos 状态目录中有一个或多个非终态工作流
- 如需检查实时 PR 相关的安全防护:
gh位于 PATH 中(orchestrate 处理程序会调用 shell 命令) - 如需检查分支活动相关的安全防护:
git位于 PATH 中
流程
第 1 步:试运行预览
始终先使用 dryRun: true。此调用会筛选候选项并评估安全防护,但不会更改任何工作流状态。
exarchos:exarchos_orchestrate({
action: "prune_stale_workflows",
args: {
dryRun: true
}
})
响应格式如下:
{
candidates: [
{ featureId: string, phase: string, workflowType: string, stalenessMinutes: number }
],
skipped: [
{ featureId: string, reason: "open-pr" | "active-branch" }
]
}
可选参数:
thresholdMinutes-- 过期时长阈值。默认值为 10080(7 天)。includeOneShot-- 是否将oneshot工作流纳入候选集。默认值为true。force-- 与试运行无关;仅在应用模式下生效(第 4 步)。
第 2 步:显示候选项表格
向用户显示表格,以便他们查看将要清理的内容。使用以下格式:
## Prune Candidates (3)
| Feature ID | Type | Phase | Stale (min) |
|---|---|---|---|
| feat-old-experiment | feature | implementing | 14430 |
| oneshot-typo-fix | oneshot | plan | 9120 |
| debug-flaky-test | debug | investigate | 8650 |
## Skipped by Safeguards (2)
| Feature ID | Reason |
|---|---|
| feat-active-pr | open-pr |
| feat-recent-work | active-branch |
如果 candidates.length === 0 且 skipped.length === 0,则输出:
没有需要清理的过期工作流。管道状态正常。
然后退出 — 不再执行其他操作。
第 3 步:请求确认
请用户在以下三个选项中选择一个:
proceed -- 清理列出的候选项(跳过的工作流将保留) abort -- 不做任何更改并退出 force -- 绕过安全防护,并同时清理跳过的工作流
等待用户明确输入。不要自动继续。
第 4a 步:应用(proceed)
用户选择 proceed 后,使用 dryRun: false 调用相同的操作。如果用户在第 1 步设置了 thresholdMinutes 和 includeOneShot,则传入这些参数。
exarchos:exarchos_orchestrate({
action: "prune_stale_workflows",
args: {
dryRun: false
}
})
此时响应会包含一个 pruned 数组:
{
candidates: [...],
skipped: [...],
pruned: [
{ featureId: string, previousPhase: string }
]
}
pruned 中的每个条目都对应一个已转换为 cancelled 状态并发出了 workflow.pruned 事件的工作流。
第 4b 步:应用(force)
用户选择 force 后,设置 force: true。安全防护会被绕过,但绕过信息会记录在 workflow.pruned 事件载荷中的 skippedSafeguards: [...] 字段里,以保留完整的审计记录。
exarchos:exarchos_orchestrate({
action: "prune_stale_workflows",
args: {
dryRun: false,
force: true
}
})
在强制模式下,试运行期间列于 skipped 列表中的工作流现在也符合清理条件。
第 4c 步:应用(abort)
用户选择 abort 后,不再第二次调用该操作,直接退出。试运行没有更改任何状态。
第 5 步:报告结果
应用调用返回后,总结执行结果:
## Prune Complete
**Pruned:** 3 workflows transitioned to cancelled
**Skipped:** 2 workflows preserved by safeguards
**Force bypass:** no
### Pruned Workflows
- feat-old-experiment (was: implementing)
- oneshot-typo-fix (was: plan)
- debug-flaky-test (was: investigate)
如果使用了 force,还要列出绕过的安全防护:
### Safeguards Bypassed
- feat-active-pr: open-pr
- feat-recent-work: active-branch
保护措施说明
每次取消前,orchestrate 处理程序都会自动运行两项保护措施:
| 保护措施 | 行为 | 原因键 |
|---|---|---|
| 开放的 PR | 如果 gh pr list --head <branch> --state open 返回任何结果,则跳过 | open-pr |
| 近期提交 | 如果 git log --since "24 hours ago" origin/<branch> 显示有提交,则跳过 | active-branch |
状态中没有 branchName 的工作流(例如在委派前停留在 ideate/plan 阶段而被放弃)不可能有 PR 或分支活动,因此保护措施会直接跳过检查,该工作流符合清理条件。
force: true 会绕过这两项检查,但不会绕过审计——被绕过的保护措施名称会记录在 workflow.pruned 事件载荷中。
错误处理
- **没有状态目录:**先初始化一个 exarchos 工作流——没有可清理的内容。
- **
gh/git不可用:**保护措施检查会因错误而直接跳过。请手动确认没有开放的 PR,然后使用force: true重新运行。 - **所有工作流都已清理:**报告“没有可清理的过期工作流”并退出(见示例 3)。
反模式
| 不要 | 应该怎么做 |
|---|---|
| 跳过试运行步骤 | 始终从 dryRun: true 开始,让用户先查看候选项 |
| 不展示表格就自动确认 | 呈现候选项表格,并等待用户明确输入 |
默认使用 force: true | 仅在用户明确选择启用时使用 force |
手动逐个调用 cancel 取消每个过期工作流 | 使用此技能——它会批量执行取消循环并发出 workflow.pruned 审计事件 |
| 每次会话都运行 | 清理属于维护操作;仅在可观察到流水线积累时运行 |
示例
示例 1:试运行无异常,用户继续
> prune
## Prune Candidates (2)
| Feature ID | Type | Phase | Stale (min) |
|---|---|---|---|
| feat-old-spike | feature | plan | 12880 |
| oneshot-readme-tweak | oneshot | implementing | 9700 |
## Skipped by Safeguards (0)
(none)
Proceed? (proceed/abort/force)
> proceed
## Prune Complete
**Pruned:** 2 workflows transitioned to cancelled
**Skipped:** 0
**Force bypass:** no
### Pruned Workflows
- feat-old-spike (was: plan)
- oneshot-readme-tweak (was: implementing)
示例 2:保护措施跳过,用户强制执行
> prune
## Prune Candidates (1)
| Feature ID | Type | Phase | Stale (min) |
|---|---|---|---|
| feat-stale-no-pr | feature | implementing | 11200 |
## Skipped by Safeguards (1)
| Feature ID | Reason |
|---|---|
| feat-stale-with-pr | open-pr |
Proceed? (proceed/abort/force)
> force
## Prune Complete
**Pruned:** 2 workflows transitioned to cancelled
**Skipped:** 0
**Force bypass:** yes
### Pruned Workflows
- feat-stale-no-pr (was: implementing)
- feat-stale-with-pr (was: implementing)
### Safeguards Bypassed
- feat-stale-with-pr: open-pr
示例 3:流水线为空
> prune
No stale workflows to prune. Pipeline is clean.
架构发现
如需了解规范参数架构和任何未来字段,请使用:
exarchos:exarchos_orchestrate({
action: "describe",
actions: ["prune_stale_workflows"]
})
Exarchos 集成
prune_stale_workflows 操作会为每个被清理的工作流发出两个事件:
workflow.cancelled(由底层handleCancel路径自动发出)workflow.pruned(由此处理程序发出,包含triggeredBy: 'manual'和可选的skippedSafeguards)
标准投影会将这两个事件都投射到工作流状态的 _events 数组中。下游视图可以筛选 workflow.pruned,以区分批量清理和用户发起的取消。