feat(workflow): 复刻 ultracode 手册并修复 worktree/inline/opt-in 三处缺口

围绕 ultracode skill 审查 agent 系统一致性后:
- ultracode.ts: 用系统提示版完整 Workflow 编排手册替换中文精简版
- HIGH#1 isolation:'worktree': claudeCodeBackend.run() 用 createAgentWorktree +
  runWithCwdOverride 包裹 runAgent + finally 清理实现真正的 cwd 隔离;slug 用
  sha256(runId:agentId) 派生以匹配 cleanupStaleAgentWorktrees 清理正则
  (修 runId 为 w+base36 非 UUID 导致的泄漏盲区);worktree.ts 注释同步修正
- HIGH#2 inline 持久化: 新增 persistInlineScript,WorkflowTool + service 两条
  inline 路径对称持久化到 .claude/workflow-runs/<runId>/script.js,返回可复用
  scriptPath(闭环 inline→编辑→scriptPath 重提迭代循环)
- HIGH#3 opt-in 分工: ultracode/WorkflowTool/effort 注明 session reminder 由
  harness 注入,repo 内无 ultracode 信号,保持 feature('WORKFLOW_SCRIPTS') +
  isEnabled 两层 gate,不自造注入
- 测试: 新增 persistInline.test.ts;扩展 claudeCodeBackend(isolation 4 用例)/
  WorkflowTool(inline)/service(scriptPath)/ultracode(harness)

含配套 workflow engine/panel 完善与 run-state-persistence design doc。

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
claude-code-best
2026-06-13 23:04:33 +08:00
parent d236880bc3
commit 54d2bf6f12
32 changed files with 2253 additions and 196 deletions

View File

@@ -16,6 +16,14 @@ export const RUN_STATUS_COLOR: Record<RunProgress['status'], string> = {
killed: 'subtle',
}
/** run 状态 → 展示文字header 用;对齐参考图 done/running。 */
export const RUN_STATUS_TEXT: Record<RunProgress['status'], string> = {
running: 'running',
completed: 'done',
failed: 'failed',
killed: 'killed',
}
/** phase 在侧栏的合并状态(含 pendingmeta 声明但未启动)。 */
export type PhaseStatus = 'running' | 'done' | 'pending'
@@ -31,23 +39,35 @@ export const PHASE_COLOR: Record<PhaseStatus, string> = {
pending: 'subtle',
}
/** agent 行的视觉三件套:标记字符 + 颜色 + 行尾文字后缀。 */
export type AgentVisual = { mark: string; color: string; suffix: string }
/** agent 行的视觉:标记字符 + 颜色running 由 UI 用 spinner 动画覆盖 mark。 */
export type AgentVisual = { mark: string; color: string }
/**
* agent 状态 → 视觉。
* - running → ● warning
* - running → ● warningUI 用 spinner 动画覆盖 mark
* - done·dead → ✗ error
* - done·okoutputShape='object' → object否则 text
* - done·ok → ✓ success
*/
export function agentVisual(a: AgentProgress): AgentVisual {
if (a.status === 'running')
return { mark: '', color: 'warning', suffix: 'running' }
if (a.resultKind === 'dead')
return { mark: '✗', color: 'error', suffix: 'dead' }
return {
mark: '✓',
color: 'success',
suffix: a.outputShape === 'object' ? 'object' : 'text',
}
if (a.status === 'running') return { mark: '●', color: 'warning' }
if (a.resultKind === 'dead') return { mark: '', color: 'error' }
return { mark: '✓', color: 'success' }
}
/** token 数 → 展示字符串(<1000 原值;否则保留 1 位小数 + k。 */
export function formatTokenCount(n: number | undefined): string {
if (!n) return '0'
return n >= 1000 ? `${(n / 1000).toFixed(1)}k` : String(n)
}
/**
* agent 行右侧统计文本:`model · Nk tok · N tool`。
* 无 model 时省略前段running 中 token/tool 由 agent_progress 实时刷新。
*/
export function agentMetaText(a: AgentProgress): string {
const parts: string[] = []
if (a.model) parts.push(a.model)
parts.push(`${formatTokenCount(a.tokenCount)} tok`)
parts.push(`${a.toolCount ?? 0} tool`)
return parts.join(' · ')
}