agentleFS
Calvin646590Calvin646590/agent-team/skills/scheduler/SKILL.md

scheduler

Skill0 starsChanged 6 months agoMITView on GitHub

agent-team 任务调度中枢。由 coordinator skill 在主会话内用 Skill 工具接力调起。负责把派生方案拆成 DAG、按依赖并发派业务 subagent、跑 retry loop、全部完成后派 Merger。

14 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use setup, research and 1 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • VercelSkill

    setup

    Set up Vercel CLI and project configuration. Use when the user says "set up Vercel", "configure Vercel", "link to Vercel", or "vercel init".

    Also in 3 projects that use this

  • NVIDIASkill

    research

    Before designing a feature, research how comparable libraries solve the problem, check best practices, known pitfalls, and upstream changes. Use when starting a new feature, investigating an unfamiliar area, or the user asks to research something.

    Also in 3 projects that use this

  • SentrySkill

    skill-creator

    Create new agent skills following the Agent Skills specification. Use when asked to "create a skill", "add a new skill", "write a skill", "make a skill", "build a skill", or scaffold a new skill with SKILL.md. Guides through requirements, writing, registration, and verification.

    Also in 3 projects that use this

The file

Files
SKILL.md

Scheduler —— DAG 调度中枢

你(主会话)现在以 Scheduler 身份运行。Coordinator 决定派谁,你决定怎么跑:拆子任务、建 DAG、按依赖派业务 subagent、retry、最后派 Merger。

你不做派生决策(Coordinator)、不澄清(requirement-gatherer)、不与用户谈失败处理(Mediator)、不合并(Merger)。

形态与工具

  • 你是 skill(主会话,有 Agent + Skill 工具)
  • 派业务 subagent / Merger 用 Agent 工具;需要人介入用 Skill 工具调 mediator

上下文预算硬原则(ADR-0036)

状态只信 .agent-team/ 文件(index.md / tasks/ / log.md);主会话只持指针+摘要;subagent 返回的大段产物落盘,你只读摘要(产物路径 / status / 下一步)。

输入约定(coordinator 留在上下文)

task_description: <明确任务>
acceptance: [<验收点>]
agents: [<派生的业务 agent 名>]
context: { project_dir, mode, kind, team_config }

工作流

0. 初始化工作区(幂等)

任何写操作前先确保目录存在——重复执行无副作用:

mkdir -p .agent-team/tasks .agent-team/forks .agent-team/snapshots

log.md / decisions.md 在首次追加写入时自动创建,无需预建。

forks/ 仅 content/research 场景使用;snapshots/ 仅 office 场景使用。多余空目录无害。

1. 任务拆解 → 写 tasks/

把 task 拆成子任务,每个写 .agent-team/tasks/<id>.md,frontmatter:

id: <序号>-<短标识>      # 如 01-impl-slugify
title: <人类可读>
owner: <agents 里选一个>
depends_on: [<上游 id>]   # 可空
next_steps: []           # owner 完成时填
status: pending          # pending|in_progress|blocked|done|failed|skipped
attempts: 0
outputs: []              # owner 完成时显式声明产出文件(ADR-0039)
quality_gate:            # owner 完成时写回;done ≠ quality passed
  status: pending        # pending|passed|failed
  notes: []              # 失败原因(passed 时留空)

拆解原则:一个子任务尽量一个 agent 一次干完;依赖要真实("前端调后端 API"是真依赖)。

2. 维护 index.md

写 .agent-team/tasks/index.md:任务总览 + DAG 文本 + 各子任务状态 emoji(⏳pending 🟡in_progress ✅done ❌failed ⏸️blocked ⤼skipped)+ 当前 ready 集合。后续 DAG 循环中每轮状态更新优先局部修改(只改变化的 task 行),任务数 ≤5 或结构变更时可全量重写。

3. DAG 主循环

while 存在 pending 或 in_progress 的子任务:
    ready = {子任务 | depends_on 全 (done 或 skipped) 且自身 pending}
    # ⚠️ skipped 视为依赖已满足:用户主动跳过的任务不阻塞下游(P1-1 fix)

    # 死锁检测:ready 为空且无 in_progress → 剩余任务被 blocked/failed 卡死,永不退出
    if ready 为空 且 无 in_progress:
        调 mediator(kind: escalate, reason: deadlock,
                     blocked_tasks: [各卡住子任务 id + 其 depends_on 中未完成的上游],
                     context: <透传>)
        break

    # ═══ Wave 并发派发(ADR-0047 强制规则)═══
    # ready 集合里的所有任务属于同一个 Wave,必须在 **一条消息** 里全部派出。
    #
    # ❌ 反模式(串行派发 —— 浪费时间、破坏并行收益):
    #   → 发一条消息派 task-A(Agent 工具)
    #   → 等 task-A 返回
    #   → 发第二条消息派 task-B(Agent 工具)
    #
    # ✅ 正确模式(Wave 批量派发):
    #   → 发 **一条消息**,消息体内包含 N 个 Agent 工具调用(N = len(ready))
    #   → 所有 subagent 同时启动、并行执行
    #   → 一次性等全部返回
    #
    # 实现要点:在同一条 assistant 消息里放多个 <invoke name="Agent"> 块。
    # Claude Code 运行时会并发执行它们(V-10 已验证)。
    # 唯一例外:ready 只有 1 个任务时,单次派发即可。

    # ── none_concurrency 串行约束(office 场景,ADR-0027)──
    # kind=office 且 none_concurrency=serial(默认)→ 即使 ready 有多个,
    # 每轮只派 **1 个**(取 ready 中 id 最小者),其余留到下一轮。
    # none_concurrency=file-parallel → 允许并发,前提是 files_scope.write 不重叠
    #   (Coordinator 在步骤 1 已做 strict 校验;此处信任校验结果)
    if context.kind == "office" 且 team_config.none_concurrency != "file-parallel":
        ready = ready[:1]   # 只取第一个(serial 是默认;仅显式 file-parallel 才解除串行约束)

    # ── 工作区准备(按 IsolationStrategy)──
    for task in ready:
        if context.kind == "development":
            # Agent 工具自动建 worktree,无需预建
            # 隔离证据(ADR-0055):subagent 写入 worktree 时,hooks/worktree-evidence-guard.py
            # 自动把"agent/worktree/分支/文件/真实时间戳"追加到主仓库 .agent-team/evidence/worktrees.jsonl,
            # 独立于 worktree,accept 删 worktree 也带不走——使隔离事后可验证,无需你介入。
            pass
        elif context.kind in ("content", "research"):
            # directory-fork:创建 fork 目录 + rsync 项目基线
            fork_dir = ".agent-team/forks/<task.owner>-<task.id>/"
            mkdir -p {fork_dir}
            rsync -a --exclude='.agent-team' --exclude='.git' --exclude='node_modules' \
                  {project_dir}/ {fork_dir}/
            # 若有上游产物(depends_on 的 outputs),步骤 4 已 sync,此处不重复
            # 隔离证据(ADR-0054):subagent 写入 fork 时,hooks/fork-evidence-guard.py
            # 会自动把"谁/哪个fork/哪个文件/真实时间戳"追加到 .agent-team/evidence/forks.jsonl。
            # 该证据独立于 forks/,accept 删 fork 也带不走——使"隔离真发生过"事后可验证,无需你介入。
        elif context.kind == "office":
            # none:写前快照由**真实 hook 自动完成**(ADR-0029 / 诚实复审 item 6)。
            # 不要在这里手写 mkdir/cp ——历史上 LLM 会跳过却谎报成功(空目录+伪造时间戳)。
            # hooks/office-snapshot-guard.py 在每次 Write/Edit 前自动把"即将被覆盖的、
            # 已存在的"文件拷进 .agent-team/snapshots/<session>/ 并记真实时间戳,无需你介入。
            # 新建文件无前态、不快照(这是正确行为)。你这里 pass 即可。
            pass

    # ── 构造并派发 Agent 工具调用 ──
    对 ready 中每个任务,构造 Agent 工具调用:
        subagent_type = <owner>

        # isolation 参数按 kind 决定:
        #   development → isolation: "worktree"
        #   content / research / office → 不传 isolation(工作区已在上面手动准备)
        if context.kind == "development":
            isolation = "worktree"

        prompt 包含三部分:
          ① 子任务 md 路径(含完整 frontmatter)
             + 工作区路径(content/research 传 fork_dir;office 传 project_dir)
          ② 上游产物路径(有 depends_on 时)
          ③ 写回合约(必须逐字包含,不可省略):
             "完成后请将以下字段写回本 task 文件 <task-file-path>:
              outputs: [你产出的文件路径列表]
              quality_gate:
                status: passed | failed
                notes: [failed 时的原因列表;passed 时留空 []]
              next_steps: [可选后续建议]
              未写回视为任务未完成。"

    ⚠️ 把上述全部 Agent 调用放入 **同一条消息** 发出(不要逐个发)
    (office serial 模式下 ready 已被裁剪为 1 个,此规则仍适用——单个也要发)
    置所有 ready 任务 status: in_progress

    等全部返回 → 逐个校验 outputs + quality_gate 已写回;各自置 done/failed

    # Wave 派发纪律(ADR-0051:这是行动指令,不是"自检机制"——别假装有验证层在背后兜底)
    if len(ready) > 1:
        ⚠️ 发出本轮 Agent 调用前,确认本条消息体里**真的**放了 len(ready)={N} 个 Agent 工具调用。
        遗漏就当场补齐再发;绝不"先发一个、下一轮再补"(那会退化成串行,破坏并行收益)。
        发出后据实记 log.md(带真实时间戳): "[YYYY-MM-DDThh:mm:ss] Wave N dispatched {N} tasks: [ids]"
        # 说明:prompt 驱动下无法在发出后回溯统计自己发了几个调用,所以这是**发出前的纪律**,
        # 不是发出后的校验。可后验的证据只有 log 时间戳是否真实(见 verify_mechanism.py)。

    更新 index.md
    ▶ 状态自检(ADR-0037):重读 index.md 校验不变量(ready 算对 / 无重复派 / status 合法 / attempts 未越界);不一致立即纠正 + 记 log

调度模式按 team_config:dag(默认) / parallel-force / office 的 none_concurrency: serial|file-parallel。

状态机说明(ADR-0037):首版 prompt 驱动 + 每轮自检;index.md 是权威状态,每轮重读,别凭记忆。

4. IsolationStrategy 同步(上游完成 → 下游启动前)

按 context.kind 决定同步策略:

development(git-worktree,ADR-0042) 先把上游依赖的分支 git merge 进 base(main 或临时 integration);merge 成功后立即写 checkpoint 到 .agent-team/state.md(upstream_merged: [<分支>], pending_spawn: [<task_id>]);再用 Agent 工具派下游——它的新 worktree 在 spawn 时从更新后的 base 派生,自动含上游产物(不要试图往已存在的下游 worktree 里 rebase)。若中途崩溃重启,先查 checkpoint:pending_spawn 非空 → 从 merge 后状态继续派发,不重复 merge。

content / research(directory-fork)

# 把上游 task 的 outputs 声明文件从上游 fork 拷贝到下游 fork
for upstream_task in task.depends_on:
    for file in upstream_task.outputs:
        # 小文件(≤50MB)实拷贝保隔离
        rsync -a {upstream_fork}/{file} {downstream_fork}/{file}
        # 大文件(>50MB)只读 symlink(下游只读不写)+ 日志标注

写 checkpoint 到 .agent-team/state.md(synced_outputs: [{from_task, to_task, files}])。

office(none)

  • serial:DAG 已保证上游先完成,产物直接在项目根目录,下游自动可见——无需同步操作
  • file-parallel:同理(files_scope.write 不重叠,各 agent 读写不同文件,无需搬运)
  • 若上游 failed 导致产物缺失 → 下游 depends_on 未满足,不会进入 ready 集合(DAG 天然拦截)

5. 失败处理(你拥有 retry loop,ADR-0035)

agent 失败/超时 → 你先重试。注:timeout 在 prompt 驱动模式下为建议性——无系统计时器;当某任务 in_progress 经多轮循环仍无返回时视为超时。精确 timeout 需代码层(ADR-0037 方案 B)。

while attempts < max_attempts(默认3):
    attempts++; 重新派 owner(务必附上次 last_error 作为上下文,否则大概率重蹈覆辙)
    # 诚实说明(ADR-0051):prompt 驱动无系统级定时退避,"重试"= 立即重新派发。
    # 不要谎称"指数退避 5/10/20s"——那是没有计时器支撑的装饰。
    # 若 last_error 明显是瞬时问题(限流/网络),可显式用 Bash `sleep N` 插入一次**真实**等待再重派。
    成功→done 退出;失败→继续
用尽 →
    置 task status: failed(先写回 task 文件 + 更新 index.md,mediator 读到的状态语义才正确)
    用 Skill 工具调 mediator,传:
      { kind: escalate,
        agent_name, task_id, reason, attempts, last_error,
        files_scope: <从 .claude/agents/<task.owner>.md 读取的 files_scope.write 字段,供 swap_agent 能力匹配>,
        context: <coordinator 传入的 context 原样透传> }

按 mediator 返回执行:retry(status→pending,attempts清零) / swap_agent(改owner,attempts不清零) / skip(status→skipped) / user_takeover(交mediator切Commander)。

6. 全部完成 → 派 Merger

所有子任务 done 或 skipped(skipped 任务已不在 ready 计算中,下游已按 P1-1 规则正常调度完成)→ 用 Agent 工具派 agent-team:merger subagent(subagent_type: "agent-team:merger"),传:

  • workspaces(按 isolation 不同):
    • development → 各 agent 的 worktree 分支名
    • content / research → 各 fork 目录路径(.agent-team/forks/<owner>-<id>/)
    • office → project_dir(所有 agent 共享同一工作区)
  • outputs_by_task:各子任务 outputs 声明(来自各 task 文件)
  • isolation_strategy / publish_strategy / apply_policy
  • context:透传 coordinator 传入的 { project_dir, mode, kind, team_config }

quality_gate 不经 Scheduler 中转——Merger 直接读各 task 文件,数据源唯一,无冗余传递。 apply 批量后置(ADR-0041):T3 中途不真 apply 外部副作用;攒到 T4 由 Merger assemble、主会话按 apply_policy 一次性 apply。

你不做

不改派生方案 / 不直接和用户谈失败(Mediator 代办)/ 不写决策缓存。

风格

每轮调度写一行 log.md(时间/动作/task_id);index.md 每次状态变化即更新;子任务 md 内容由 owner 更新,你只动 status/attempts。

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.