dagr-producer
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesedagr producer — write the run, prove the run
dagr 生产者——编写运行文件,验证运行过程
You are the producer: the single writer of a run file that
renders live. dagr is a representation kernel: you assert task truth, and
it derives only defined view signals from those facts. Missing or wrong facts
still produce a missing or wrong graph; there is no workflow engine to repair it.
dagr viewContract version: (v1/v2 files remain readable; write v3 for new runs).
"dagr": 3你作为生产者:是实时渲染的运行文件的唯一编写者。dagr是一个表示核心:你断言任务的真实状态,它仅从这些事实中推导定义好的视图信号。缺失或错误的事实仍会生成缺失或错误的图;没有工作流引擎会自动修复它。
dagr view契约版本:(v1/v2版本的文件仍可读取;新运行请使用v3版本)。
"dagr": 3Find your validator (before you write anything)
找到你的验证器(编写任何内容之前)
The check loop below is the only feedback you get, so resolve the
binary FIRST and stop if you can't:
dagr- if set;
$DAGR_BIN - (on PATH);
command -v dagr - the plugin/repo build: — inside a herdr pane the runtime injects
<dagr repo>/target/release/dagr, which IS the dagr repo root;$HERDR_PLUGIN_ROOT - fallback: .
cargo run --manifest-path <dagr repo>/Cargo.toml -- check …
No validator available → do not start writing run files; say so and
stop. An unvalidated run file is exactly the silent wrongness this whole
system exists to prevent.
下面的检查循环是你能获得的唯一反馈,因此请先确定二进制文件的位置,若无法找到则停止操作:
dagr- 若已设置,则使用该路径;
$DAGR_BIN - 使用(在PATH环境变量中查找);
command -v dagr - 插件/仓库构建版本:——在herdr面板中,运行时会注入
<dagr repo>/target/release/dagr,该路径即为dagr仓库根目录;$HERDR_PLUGIN_ROOT - 备选方案:。
cargo run --manifest-path <dagr repo>/Cargo.toml -- check …
若没有可用的验证器→请勿开始编写运行文件;告知相关情况并停止操作。未经验证的运行文件正是这套系统要避免的隐性错误。
The loop (non-negotiable)
核心循环(不可妥协)
write run.json.tmp → dagr check run.json.tmp --strict --json → fix → repeat until []
→ THEN rename over run.jsonValidate the candidate, then publish it — never the other way around.
The pane renders whatever holds, immediately; renaming an
invalid candidate over it shows your error state to every viewer while
you iterate. The safe transaction:
run.json- Write the complete next document to (same directory — rename must be atomic, so same filesystem).
run.json.tmp - . Exit 0 with
dagr check run.json.tmp --strict --jsonis clean; exit 1 means findings (E-codes are errors; W-codes mean representable- but-suspect — fix them unless you can say why not;[]treats them as failures, prefer it). Exit 2 means the validator could not read the file at all — a path or tooling problem, never a document problem; stdout is empty on that path, so never treat empty output as clean. Stop, re-run the preflight, and never publish on a non-zero exit.--strict - Only when clean: (atomic rename — the pane reloads on mtime and never sees a half-written or invalid file).
mv run.json.tmp run.json - On failure: fix the temp file and re-check. The previous live file
stays untouched — never leave itself in an error state.
run.json
Where to write it: the pane looks for first, then
, then under the workspace cwd — and waits on
when none exists yet. Default to in
the workspace root (gitignore it), and one run per file: parallel lanes
inside a run are just tasks with disjoint , but a separate
workflow gets its own run file and its own pane.
$DAGR_RUN.dagr/run.jsonrun.json.dagr/run.json.dagr/run.jsondepswrite run.json.tmp → dagr check run.json.tmp --strict --json → fix → repeat until []
→ THEN rename over run.json先验证候选文件,再发布——绝不能颠倒顺序。
面板会立即渲染中的内容;将无效候选文件重命名覆盖原文件会在你迭代过程中向所有查看者展示错误状态。安全的操作流程:
run.json- 将完整的下一版文档写入(需在同一目录下——重命名操作必须是原子性的,因此要在同一文件系统中)。
run.json.tmp - 执行。返回码为0且输出
dagr check run.json.tmp --strict --json表示验证通过;返回码为1表示存在问题(E开头的代码为错误;W开头的代码表示内容可表示但存在疑点——除非你能说明无需修复的理由,否则请修复;[]会将其视为失败,推荐使用该参数)。返回码为2表示验证器根本无法读取文件——这是路径或工具问题,而非文档问题;此时标准输出为空,因此绝不能将空输出视为验证通过。停止操作,重新执行预检查,返回码非零时绝不能发布。--strict - 仅当验证通过后:执行(原子重命名——面板会根据修改时间重新加载,绝不会看到半写入或无效的文件)。
mv run.json.tmp run.json - 若验证失败:修复临时文件并重新检查。之前的在线文件会保持不变——绝不能让处于错误状态。
run.json
运行文件的写入位置:面板会优先查找,其次是,最后是工作区当前目录下的——当以上路径都不存在时,会等待的创建。默认写入工作区根目录下的(将其加入git忽略列表),每个运行对应一个文件:运行内的并行分支只需设置不相交的即可,而独立的工作流需要单独的运行文件和面板。
$DAGR_RUN.dagr/run.jsonrun.json.dagr/run.json.dagr/run.jsondepsObject model in one breath
一句话总结对象模型
- Project = the recursive visual scope. The run is the implicit root;
may have
projects[]. A phase or workstream is just a project, not another entity. Each task has one optionalparenthome, while its dependency edges may cross any project boundary.project - Task = the work item. Stable you choose (never a pane id).
idis an open set —kind— pick the honest one (impl · review · test · gate · question · docs · ship · …for a task that exists to be answered by a human,questionfor fan-ins; both change how dagr draws it). States:gate.queued · working · review · blocked · done · failed · rejected · canceled · settled_unverified - Attempt = one try at a task. styled
id, 1-basedT·aN. States:n. A retry never rewrites an attempt — it appends a new one with aqueued · working · done · failed · rejected · settled_unverified · lost. A task's history never moves backward — you never rewrite or delete an attempt. A task's state follows its latest attempt, so a send-back moves acausetask back todoneas its new attempt opens.working - Event = append-only provenance: , ascending
attempt_started · attempt_settled · promoted · directive · message_resolved · notetimestamps. Never rewrite or reorder events.at - Evidence tier on every terminal outcome: (mechanically checked — test run, commit receipt) ·
verified(typed envelope from the actor) ·reported(inferred) ·heuristic(bare claim). "The agent said done" is at bestasserted. Missing envelope? That'sreported— a real terminal state, not a softsettled_unverified.done
- Project(项目) = 递归可视化范围。运行文件是隐式根节点;可包含
projects[]字段。阶段或工作流只是一个项目,而非其他实体。每个任务可选择归属一个parent,而其依赖关系可跨越任何项目边界。project - Task(任务) = 工作项。由你选择稳定的(绝不能使用面板ID)。
id是开放集合——kind——选择最贴合实际的类型(impl · review · test · gate · question · docs · ship · …用于需要人类回答的任务,question用于扇入场景;两者会改变dagr的渲染方式)。状态包括:gate。queued · working · review · blocked · done · failed · rejected · canceled · settled_unverified - Attempt(尝试) = 任务的一次执行尝试。格式为
id,其中T·aN从1开始递增。状态包括:n。**重试绝不会重写已有尝试——而是追加一个带有queued · working · done · failed · rejected · settled_unverified · lost的新尝试。**任务的历史绝不会回退——你绝不能重写或删除尝试记录。任务的状态由最新尝试的状态决定,因此当任务被退回时,新尝试启动后,cause状态的任务会回到done状态。working - Event(事件) = 仅可追加的溯源记录:,按
attempt_started · attempt_settled · promoted · directive · message_resolved · note时间戳升序排列。绝不能重写或重新排序事件。at - Evidence tier(证据层级) 适用于所有最终结果:(机械检查——测试运行、提交回执)·
verified(来自执行者的结构化信封)·reported(推断得出)·heuristic(无证据声明)。“Agent称已完成”最多属于asserted层级。若缺少信封?则状态为reported——这是一个真实的最终状态,而非宽松的settled_unverified。done
Invariants dagr check will hold you to
dagr check强制执行的不变规则
- Task state is a projection over attempts: needs a working attempt;
working/done/rejectedneed the latest attempt to match;settled_unverifiedaccepts a latest attempt offailedorfailed;lostforbids a working attempt, and forbids a latest attempt ofqueuedordone— a task re-queued after asettled_unverifiedorfailedattempt is correct and expected;rejectedneeds at least one attempt.reviewis task-only: it withdraws planned work without rewriting or inventing an attempt.canceled - Causes point backward in time: attempt n>1 carries
(
cause) whosesent_back · gate_failed · followup · supersedednames an earlier attempt.refonly for n=1.initial - The run is a DAG: no cycles through or gate
deps. A gate's fan-in IS itsinputs;depsexists only to override when the fan-in set differs from the dependency set. Encode true sequential work as dependencies; task declaration order is only the attempt-less sibling tiebreak.inputs - Terminal attempts carry with
outcome==resultand a real evidence tier; timestamps are real ISO-8601 and attempts end after they start.state - Ids are yours and unique: task ids never collide
with attempt ids. herdr pane ids go in , never in
locator.id - Live attempts are locatable and alive: working attempts want a
(
locator) and a populated{"pane": "wX:pN"}—liveness(bool),prompt_acknowledged(timestamp string),last_output_at(count of composer lines typed but unsubmitted,queued_inputwhen none — a number, not a bool; a bool rejects the whole document). Update0when your agents produce output; staleness is rendered, silence is the enemy.last_output_at - Blocked names its unblocker; promotion is an event, not
an inference — emit when a fan-in completes.
{"type": "promoted", "task": ...} - Project containment is not dependency. Give each task one truthful
visual home; keep every blocker in , including cross-project edges. Never duplicate a task into two projects to make both impacts visible.
deps - Operator messages retain their authority and id. The pane delivers a
envelope to you. Respect
[DAGR OPERATOR MESSAGE]versusrecommend_and_return; preservemay_decide_and_continuein the resolution event. dagr transports the request but does not act on it for you.message_id
- 任务状态是尝试记录的投影:状态需要存在一个处于working状态的尝试;
working/done/rejected状态需要最新尝试的状态与之匹配;settled_unverified状态允许最新尝试为failed或failed;lost状态禁止存在working状态的尝试,且禁止最新尝试为queued或done——任务在settled_unverified或failed尝试后重新进入queued状态是合理且符合预期的;rejected状态需要至少存在一个尝试。review是任务独有的状态:它会撤销计划中的工作,无需重写或创建尝试记录。canceled - 原因指向时间更早的记录:第n>1次尝试需携带(
cause),其sent_back · gate_failed · followup · superseded字段指向更早的尝试记录。ref仅用于第1次尝试。initial - 运行文件是DAG结构:通过或gate的
deps不会形成循环。Gate的扇入集合就是其inputs——这样可确保所有gate边都在循环检查范围内。仅当扇入集合与依赖集合确实不同时,才使用deps字段。将真实的顺序工作编码为依赖关系;任务声明顺序仅用于无尝试记录的同级任务的排序,以及gate状态连接条的排序。inputs - 最终状态的尝试需携带:
outcome必须与状态一致,且包含真实的证据层级;时间戳为有效的ISO-8601格式,且尝试的结束时间晚于开始时间。result - ID由你定义且唯一:任务ID绝不能与尝试ID冲突。herdr面板ID需放入字段,绝不能放入
locator字段。id - 活跃尝试需可定位且保持活跃:working状态的尝试需要(
locator)和完整的{"pane": "wX:pN"}字段——liveness(布尔值)、prompt_acknowledged(时间戳字符串)、last_output_at(已输入但未提交的编辑器行数计数,无内容时为queued_input——必须是数字,不能是布尔值;若为布尔值会导致整个文档被拒绝)。当你的Agent产生输出时,更新0字段;状态过期会被渲染出来,沉默是最大的问题。last_output_at - Blocked状态需指明解锁条件;Promotion是一个事件,而非推断结果——当扇入完成时,需发送事件。
{"type": "promoted", "task": ...} - 项目归属不等于依赖关系。为每个任务指定一个真实的可视化归属;将所有阻塞项放入,包括跨项目的依赖边。绝不能为了展示影响而将一个任务复制到两个项目中。
deps - 操作员消息保留其权限和ID。面板会向你传递信封。请区分
[DAGR OPERATOR MESSAGE]与recommend_and_return;在决议事件中保留may_decide_and_continue。dagr仅负责传输请求,不会替你执行操作。message_id
Recipes
实践指南
Every recipe below has a complete, strict-clean companion document under
in this skill directory — held clean by the dagr test suite.
The fragments here show the shape; when you assemble a real file, crib
from the example, because the fragments alone omit cross-references (a
needs its referent declared, a working attempt needs
locator + liveness) that will hold you to.
examples/cause.refdagr check以下每个指南都配有完整、严格验证通过的示例文档,位于本技能目录下的文件夹中——由dagr测试套件确保其有效性。此处的片段仅展示结构;当你组装真实文件时,请参考示例,因为单独的片段会遗漏要求的交叉引用(需要指向已声明的记录,working状态的尝试需要locator + liveness字段)。
examples/dagr checkcause.refInitialize a run
初始化运行文件
json
{
"dagr": 3,
"run": {
"id": "run-myjob-v01", "title": "what this run is",
"started_at": "2026-02-01T09:00:00Z",
"orchestrator": {"pane": "wX:p1"}
},
"generated_at": "2026-02-01T09:00:00Z",
"projects": [],
"tasks": [],
"events": []
}Refresh on every write — it anchors every "Nm ago" on
screen, and a stale value renders a staleness banner.
generated_atSet automatically from your own when
available (or a stable Herdr agent target otherwise). This is where
queues operator messages; do not point it at a worker. No user onboarding
step or extra controller is required.
run.orchestrator$HERDR_PANE_IDmjson
{
"dagr": 3,
"run": {
"id": "run-myjob-v01", "title": "本次运行的描述",
"started_at": "2026-02-01T09:00:00Z",
"orchestrator": {"pane": "wX:p1"}
},
"generated_at": "2026-02-01T09:00:00Z",
"projects": [],
"tasks": [],
"events": []
}每次写入时更新字段——它是屏幕上所有“N分钟前”显示的锚点,过期的值会渲染出过期提示横幅。
generated_at若可用,自动从你自己的设置(否则使用稳定的Herdr Agent目标)。这是操作员消息的队列位置;请勿将其指向工作节点。无需用户入门步骤或额外控制器。
$HERDR_PANE_IDrun.orchestratorShape projects before tasks
先定义项目结构,再创建任务
Use the smallest hierarchy that provides honest visual homes. Do not create
separate or arrays:
phasesworkstreamsjson
"projects": [
{"id": "APP", "title": "Application"},
{"id": "API", "title": "API stream", "parent": "APP", "owner": "api-lead"},
{"id": "UI", "title": "UI stream", "parent": "APP", "owner": "ui-lead"}
]A task in uses . If a UI task depends on it, keep
the UI task in and put the API task id in its ; the renderer shows
the cross-project edge. Do not duplicate the task or force it into the
common parent. Omit only for genuinely run-level work.
API"project": "API"UIdepsprojectStart coarse: declare the useful project skeleton, immediate work, and
meaningful gates. Add discovered tasks as they become relevant; publish
operator-visible work, not every internal agent, tool, or runtime step.
Dagr derives queued-row , , , and
from , /, and ; never encode those as extra fields.
waitsreadyunassignedneeds answerdepsowneractorkind使用最小的层级结构来提供真实的可视化归属。不要创建单独的或数组:
phasesworkstreamsjson
"projects": [
{"id": "APP", "title": "应用程序"},
{"id": "API", "title": "API工作流", "parent": "APP", "owner": "api-lead"},
{"id": "UI", "title": "UI工作流", "parent": "APP", "owner": "ui-lead"}
]归属的任务需设置。若UI任务依赖该API任务,请将UI任务保留在项目中,并将API任务ID放入其字段;渲染器会显示跨项目的依赖边。绝不能复制任务或强制将其放入公共父项目。仅当任务属于运行级别的工作时,才省略字段。
API"project": "API"UIdepsproject从粗粒度开始:声明有用的项目框架、即时工作和有意义的闸门。当发现新任务变得相关时再添加;发布操作员可见的工作,而非每个内部Agent、工具或运行时步骤。Dagr会根据、/和字段推导出队列行的、、和状态;绝不要将这些编码为额外字段。
depsowneractorkindwaitsreadyunassignedneeds answerOpen a task and start its first attempt
创建任务并启动第一次尝试
json
{
"id": "L1", "title": "impl: core lane", "kind": "impl",
"owner": "l1-dev", "state": "working", "deps": [],
"attempts": [{
"id": "L1·a1", "n": 1, "cause": {"type": "initial"},
"actor": "l1-dev", "model": "fable",
"locator": {"pane": "wX:p3"},
"state": "working", "started_at": "2026-02-01T09:05:00Z",
"liveness": {"prompt_acknowledged": true, "last_output_at": "2026-02-01T09:05:00Z"}
}]
}Append
to .
{"at": ..., "type": "attempt_started", "task": "L1", "attempt": "L1·a1", "actor": "l1-dev"}eventsmodelmodel·effortfable·xhighsol5.6·maxluna5.6·maxterra5.6·maxterra5.6·maxjson
{
"id": "L1", "title": "实现:核心分支", "kind": "impl",
"owner": "l1-dev", "state": "working", "deps": [],
"attempts": [{
"id": "L1·a1", "n": 1, "cause": {"type": "initial"},
"actor": "l1-dev", "model": "fable",
"locator": {"pane": "wX:p3"},
"state": "working", "started_at": "2026-02-01T09:05:00Z",
"liveness": {"prompt_acknowledged": true, "last_output_at": "2026-02-01T09:05:00Z"}
}]
}在数组中追加。
events{"at": ..., "type": "attempt_started", "task": "L1", "attempt": "L1·a1", "actor": "l1-dev"}modelmodel·effortfable·xhighsol5.6·maxluna5.6·maxterra5.6·maxterra5.6·maxSettle an attempt (with proof)
完成尝试(附带证据)
Set attempt , , and ( must equal the
state); mirror the task ; append an event.
( is when the work stopped; the settled event's is when
the verdict landed — they may differ, and the gap is real information:
a pane that stopped at 09:50 whose rejection landed at 10:12 records
both.) Prefer the strongest evidence you have.
stateended_atoutcomeresultstateattempt_settledended_atatThe decision rule: the tier describes your evidence for the
settlement claim. requires that someone claimed completion —
however weakly; the tier grades the claim's evidence. When nobody
claimed anything and you are inferring from a runtime signal (pane
exit, silence, a green prompt), the state is — that
is what the state is for. The four honest settlements, spelled out
completely in
:
donesettled_unverifiedexamples/06-evidence-tiers.json- verified — mechanical receipt:
{"result": "done", "evidence": "verified", "receipt": "cargo test 40/40 ✓ @ a1b2c3d"} - reported — a typed envelope from the actor (structured result
data, not chat prose):
{"result": "done", "evidence": "reported", "receipt": "result envelope: {files: 4, status: complete}"} - asserted — the actor claimed completion, but only as prose:
{"result": "done", "evidence": "asserted", "reason": "actor asserted completion in chat; no typed envelope to verify against"} - nobody claimed anything — that is not a soft , it is the distinct terminal state
done, and it still needssettled_unverifiedand a matching outcome:ended_at. It never upgrades unproven work to success."state": "settled_unverified", "ended_at": ..., "outcome": {"result": "settled_unverified", "evidence": "heuristic", "reason": "no claim of completion from the actor; inferring from clean pane exit"}
设置尝试的、和(必须与状态一致);同步更新任务的;追加事件。(是工作停止的时间;settled事件的是* verdict*下达的时间——两者可能不同,时间差是真实信息:比如面板在09:50停止,而拒绝通知在10:12到达,需记录这两个时间。)请优先使用你能获取的最强证据。
stateended_atoutcomeresultstateattempt_settledended_atat决策规则:证据层级描述了你对完成声明的证据支持。状态要求有人声称已完成——无论证据多薄弱;证据层级用于评估声明的可信度。当无人声称完成且你从运行时信号(面板退出、沉默、绿色提示)推断时,状态为——这正是该状态的用途。四种真实的完成状态在中有完整说明:
donesettled_unverifiedexamples/06-evidence-tiers.json- verified——机械回执:
{"result": "done", "evidence": "verified", "receipt": "cargo test 40/40 ✓ @ a1b2c3d"} - reported——来自执行者的结构化信封(结构化结果数据,而非聊天文本):
{"result": "done", "evidence": "reported", "receipt": "result envelope: {files: 4, status: complete}"} - asserted——执行者声称已完成,但仅以文本形式:
{"result": "done", "evidence": "asserted", "reason": "执行者在聊天中声称已完成;无结构化信封可验证"} - 无人声称完成——这不是宽松的,而是明确的最终状态
done,仍需settled_unverified和匹配的ended_at:outcome。它绝不会将未经验证的工作升级为成功。"state": "settled_unverified", "ended_at": ..., "outcome": {"result": "settled_unverified", "evidence": "heuristic", "reason": "执行者未声称完成;从面板正常退出推断"}
Send back and re-enter
退回任务并重新执行
A reviewer rejecting work touches THREE records — the review attempt
settles (the review itself succeeded), the reviewed attempt
settles , and the fix round is a new attempt whose
points at the review attempt:
donerejectedcausejson
{"id": "L1·a2", "n": 2,
"cause": {"type": "sent_back", "by": "rev-1", "ref": "R1·a1", "reason": "error paths untested"},
"locator": {"pane": "wX:p3"}, "state": "working", "started_at": "...",
"liveness": {"prompt_acknowledged": true, "last_output_at": "..."}}cause.refR1·a1state: "working"examples/03-send-back.json审核者拒绝工作时需修改三个记录——审核尝试的状态设为(审核本身成功),被审核的尝试状态设为,修复轮次作为新尝试,其指向审核尝试:
donerejectedcausejson
{"id": "L1·a2", "n": 2,
"cause": {"type": "sent_back", "by": "rev-1", "ref": "R1·a1", "reason": "错误路径未测试"},
"locator": {"pane": "wX:p3"}, "state": "working", "started_at": "...",
"liveness": {"prompt_acknowledged": true, "last_output_at": "..."}}cause.refR1·a1state: "working"examples/03-send-back.jsonGate a fan-in
扇入闸门
A gate's fan-in is its — that keeps every gate edge inside the
cycle check. Use only when the fan-in set genuinely
differs from the dependency set:
depsinputsjson
{"id": "G1", "title": "gate: merge lanes", "kind": "gate", "owner": "orchestrator",
"project": "APP", "criteria": "API and UI reviews are clean",
"state": "queued", "deps": ["L1", "L2", "L3"], "attempts": []}Declare gate inputs in the intentional human reading order, and keep the
whole array intentional too: dagr preserves declaration order for
attempt-less siblings and for the gate's state-bearing join strip. Do not
rename ids for sorting, attach the gate to one lane as a layout workaround,
or add a synthetic "join" task. Declare the truthful fan-in. A gate with
is a milestone in that project; without one, dagr places it at the
nearest project shared by all inputs. Therefore a gate local to stays
inside , a gate joining and lives in their parent , and a
gate joining unrelated top-level projects is a run-level milestone. Input
attempt timestamps never choose its parent. Each direct input renders as
waiting, working, or satisfied (plus the normal
blocked/review/failure marks). On narrow panes it aggregates those marks; a
selected gate still reveals the exact input ids.
tasksprojectAPIAPIAPIUIAPP○◎●Prefer an explicit when the organizational ownership is known;
omit it when inference from input homes is the truthful answer. Never add a
fake dependency solely to move a gate on screen.
projectWhen the last input lands, append a event — with its
timestamp, like every event:
promotedatjson
{"at": "...", "type": "promoted", "task": "G1", "detail": "fan-in complete: L1 ✓, L2 ✓"}"Moving the gate forward" means the projection rules still apply: a gate
at / needs its own attempt in that state — open
(with locator + liveness if live) when the gate's work starts,
and settle it with evidence like any other attempt. A gate with
can be , or when the gate was withdrawn.
Complete document:
.
workingdoneG1·a1attempts: []queuedcanceledexamples/04-gate-promotion.json闸门的扇入集合就是其——这样可确保所有闸门边都在循环检查范围内。仅当扇入集合与依赖集合确实不同时,才使用字段:
depsinputsjson
{"id": "G1", "title": "闸门:合并分支", "kind": "gate", "owner": "orchestrator",
"project": "APP", "criteria": "API和UI审核通过",
"state": "queued", "deps": ["L1", "L2", "L3"], "attempts": []}按照人类阅读的逻辑顺序声明闸门输入,同时保持整个数组的逻辑顺序:dagr会保留无尝试记录的同级任务的声明顺序,以及闸门状态连接条的顺序。不要为了排序而重命名ID,不要将闸门附加到某个分支作为布局变通方案,也不要添加合成的“合并”任务。声明真实的扇入集合。带有的闸门是该项目中的里程碑;若没有,dagr会将其放置在所有输入共同归属的最近项目中。因此,属于的闸门会留在中,连接和的闸门会位于其父项目中,连接无关顶级项目的闸门则是运行级别的里程碑。输入尝试的时间戳不会决定其父项目。每个直接输入会渲染为(等待)、(进行中)或(已完成)(加上正常的阻塞/审核/失败标记)。在窄面板上会聚合这些标记;选中闸门仍会显示确切的输入ID。
tasksprojectprojectAPIAPIAPIUIAPP○◎●当组织归属已知时,优先使用显式的字段;当从输入归属推断更符合实际时,省略该字段。绝不要仅为了在屏幕上移动闸门而添加虚假依赖。
project当最后一个输入完成时,追加事件——必须包含时间戳,如同所有事件:
promotedatjson
{"at": "...", "type": "promoted", "task": "G1", "detail": "扇入完成:L1 ✓, L2 ✓"}“推进闸门”意味着仍需遵循投影规则:处于/状态的闸门需要自身处于对应状态的尝试——当闸门工作开始时,创建(若为活跃状态则需locator + liveness字段),并像其他尝试一样附带证据完成它。的闸门可以是状态,或在闸门被撤销时设为状态。完整文档:。
workingdoneG1·a1attempts: []queuedcanceledexamples/04-gate-promotion.jsonCancel planned work
取消计划中的工作
Set the task to and give a short ; keep all prior
attempts and events unchanged. There is no canceled attempt outcome. Because
cancellation is not success, update or cancel any task that still depends on it.
"state": "canceled"note将任务状态设为并添加简短的;保留所有之前的尝试和事件记录。不存在canceled状态的尝试结果。由于取消不等于成功,请更新或取消所有依赖该任务的其他任务。
"state": "canceled"noteDeclare loop policy (futures), don't imply it
声明循环策略(未来任务),而非隐含
json
"policy": {"rounds_max": 3, "futures": [
{"on": "pass", "ref": "G1"},
{"on": "fail", "node": {"id": "L1·a2", "title": "fix round", "actor": "l1-dev"}, "loop_back": true},
{"on": "fail", "streak": 2,
"node": {"id": "L1x·a1", "title": "escalate: fresh approach", "attribution": "predicted"},
"after": "L1·a2", "source": "two-strikes rule"}
]}ref»node○⟲loop_back≈attributionpredictedafterexamples/05a-policy-declared.jsonjson
"policy": {"rounds_max": 3, "futures": [
{"on": "pass", "ref": "G1"},
{"on": "fail", "node": {"id": "L1·a2", "title": "修复轮次", "actor": "l1-dev"}, "loop_back": true},
{"on": "fail", "streak": 2,
"node": {"id": "L1x·a1", "title": "升级:新方案", "attribution": "predicted"},
"after": "L1·a2", "source": "两次失败规则"}
]}ref»node○loop_back⟲attributionpredicted≈afterexamples/05a-policy-declared.jsonMaterialize a future (when the predicted round actually starts)
实现未来任务(当预测的轮次实际开始时)
policyattemptsevents- Remove the consumed future node from . Leaving it would collide with the real attempt's id, which the check rejects.
policy.futures - Repair chains that targeted the removed node: a sibling future that chained
afternow hangs off the task directly (drop its"after": "L1·a2") or off another still-future sibling.after - Append the real attempt with the id the future predicted, a
pointing at the trigger (
causeref'ing the failed attempt for a loop-back fix round;followupwhen a gate bounced it), locator + liveness if live.gate_failed - Append the event. Never touch prior attempts or events.
attempt_started
Before/after pair, both strict-clean:
→
.
examples/05a-policy-declared.jsonexamples/05b-policy-materialized.jsonpolicyattemptsevents- 从中移除已消耗的未来任务节点。保留它会与真实尝试的ID冲突,导致检查失败。
policy.futures - 修复指向已移除节点的链:若某个同级未来任务的
after,现在需直接连接到任务本身(删除其"after": "L1·a2"字段)或其他仍为未来状态的同级任务。after - 追加真实尝试,使用未来任务预测的ID,指向触发事件(循环修复轮次使用
cause指向失败的尝试;闸门退回时使用followup),若为活跃状态则需locator + liveness字段。gate_failed - 追加事件。绝不要修改之前的尝试或事件记录。
attempt_started
前后对比的严格验证通过文档: → 。
examples/05a-policy-declared.jsonexamples/05b-policy-materialized.jsonRecord a human decision
记录人工决策
json
{"at": "...", "type": "directive", "verb": "reject", "by": "operator",
"task": "L1", "detail": "error paths untested"}Verbs: . Directives are the decisions
log; chat prose is not.
reject · unblock · answer · rulejson
{"at": "...", "type": "directive", "verb": "reject", "by": "operator",
"task": "L1", "detail": "错误路径未测试"}动词包括:。指令是决策日志;聊天文本不属于此类。
reject · unblock · answer · ruleAnswer a question (settle a task by directive)
回答问题(通过指令完成任务)
A queued whose dependencies are done appears as in
the attention queue; the producer declares no separate readiness field.
A directive event alone cannot settle a task — task state is a
projection over attempts, so the human's answer needs an
attempt whose actor is the human. Write both in the same candidate:
questionneeds answerjson
{"id": "Q1", "title": "question: retry budget?", "kind": "question",
"owner": "operator", "state": "done", "deps": [],
"attempts": [{
"id": "Q1·a1", "n": 1, "cause": {"type": "initial"},
"actor": "operator", "state": "done",
"started_at": "2026-02-01T09:40:00Z", "ended_at": "2026-02-01T09:42:00Z",
"outcome": {"result": "done", "evidence": "reported",
"receipt": "directive answer: retry budget 2 rounds"}}]}plus the event:
json
{"at": "2026-02-01T09:42:00Z", "type": "directive", "verb": "answer",
"by": "operator", "task": "Q1", "detail": "retry budget 2 rounds"}The receipt quotes the answer; the directive is the decision-log entry.
The same pattern settles any human-resolved task (an unblock that closes
a , a rule that retires a task). Complete document:
.
questionexamples/07-answer-question.json依赖项已完成的queued状态任务会在关注队列中显示为;生产者无需声明单独的就绪字段。仅靠指令事件无法完成任务——任务状态是尝试记录的投影,因此人类的回答需要一个以人类为执行者的尝试记录。请在同一个候选文档中完成以下内容:
questionneeds answerjson
{"id": "Q1", "title": "问题:重试预算?", "kind": "question",
"owner": "operator", "state": "done", "deps": [],
"attempts": [{
"id": "Q1·a1", "n": 1, "cause": {"type": "initial"},
"actor": "operator", "state": "done",
"started_at": "2026-02-01T09:40:00Z", "ended_at": "2026-02-01T09:42:00Z",
"outcome": {"result": "done", "evidence": "reported",
"receipt": "指令回答:重试预算为2轮"}}]}加上事件:
json
{"at": "2026-02-01T09:42:00Z", "type": "directive", "verb": "answer",
"by": "operator", "task": "Q1", "detail": "重试预算为2轮"}回执引用回答内容;指令是决策日志条目。同一模式适用于任何人工解决的任务(解除阻塞以关闭任务,通过规则终止任务)。完整文档:。
questionexamples/07-answer-question.jsonHandle an operator message
处理操作员消息
The pane's default action is one contextual message composer. Herdr queues
the finished message directly to the locator, so do not
build another inbox daemon. You receive an envelope like:
run.orchestratortext
[DAGR OPERATOR MESSAGE]
message_id: msg-0123456789abcdef
run: run-myjob-v01
revision: 2026-02-01T09:42:00Z
target: G1
starter: get-guidance
authority: recommend_and_return
Ask sol5.6·max and fable·xhigh independently, then combine their opinions.Do this:
- Acknowledge the message. Treat the raw prose as instructions about the named target, bounded by the existing run scope.
- Obey authority independently of prose:
means do the analysis and return the choice;
recommend_and_returnlets you decide and proceed. Never infer the second from wording such as “best guess”.may_decide_and_continue - Treat model, reasoning, and multi-agent requests as ordinary editable instructions and use your normal orchestration tools. dagr runs none of it.
- Keep the through follow-ups. On resolution, append an event:
message_id
json
{"at":"2026-02-01T09:50:00Z","type":"message_resolved","task":"G1",
"message_id":"msg-0123456789abcdef",
"detail":"recommended option B after two independent reviews; awaiting operator"}If several messages informed one decision, set on the
directive/resolution event. Do not edit ; dagr owns that
append-only delivery journal. Your event is the durable project-memory link
back to it.
source_messagesmessages.jsonl面板的默认操作是一个上下文消息编辑器。Herdr会将完成的消息直接发送到指定的位置,因此无需构建其他收件箱守护进程。你会收到如下格式的信封:
run.orchestratortext
[DAGR OPERATOR MESSAGE]
message_id: msg-0123456789abcdef
run: run-myjob-v01
revision: 2026-02-01T09:42:00Z
target: G1
starter: get-guidance
authority: recommend_and_return
分别咨询sol5.6·max和fable·xhigh,然后汇总他们的意见。请执行以下操作:
- 确认收到消息。将原始文本视为针对指定目标的指令,且需在现有运行范围内执行。
- 独立于文本内容遵守权限规则:意味着需执行分析并返回选择;
recommend_and_return允许你自行决策并继续。绝不能从“最佳猜测”等措辞中推断出第二种权限。may_decide_and_continue - 将模型、推理和多Agent请求视为普通可编辑指令,并使用你常用的编排工具。dagr不会执行这些操作。
- 在后续操作中保留。完成决议后,追加事件:
message_id
json
{"at":"2026-02-01T09:50:00Z","type":"message_resolved","task":"G1",
"message_id":"msg-0123456789abcdef",
"detail":"两次独立审核后推荐选项B;等待操作员确认"}若多个消息影响了一个决策,请在指令/决议事件中设置字段。不要编辑;dagr拥有这个仅可追加的交付日志。你的事件是将决策与日志关联的持久化项目记忆链接。
source_messagesmessages.jsonlCustomize the three prompt starters when asked
根据需求自定义三个提示启动器
There is no onboarding step. The built-ins (Use judgment, Get guidance,
Snooze) are available by default. If the user asks to add or change an action, atomically
write beside the run file:
actions.jsonjson
{
"version": 1,
"include_defaults": true,
"actions": [
{"id":"architecture-council", "label":"Architecture council",
"prompt":"Ask two independent architecture reviewers and synthesize.",
"authority":"recommend"}
]
}Each action is only a prefilled editable prompt plus
authority. Keep the list small; prefer one flexible starter over many rigid
buttons. An id matching a built-in overrides it.
replaces the built-ins. Config version is the supported shape; at most
nine starters are shown, labels are capped at 80 bytes, and prompts at 32 KiB.
The pane reloads this file automatically and shows a banner for invalid or
unsupported configuration.
recommend|decideinclude_defaults: false1Old top-level run values are readable but inert. Do not add them.
actions无需入门步骤。默认提供内置启动器(Use judgment、Get guidance、Snooze)。若用户要求添加或修改操作,请在运行文件旁原子性地写入:
actions.jsonjson
{
"version": 1,
"include_defaults": true,
"actions": [
{"id":"architecture-council", "label":"架构委员会",
"prompt":"咨询两位独立的架构审核者并汇总意见。",
"authority":"recommend"}
]
}每个操作仅包含预填充的可编辑提示和权限。请保持列表简短;优先选择一个灵活的启动器而非多个固定按钮。与内置启动器ID匹配的项会覆盖内置启动器。会替换内置启动器。配置版本是支持的格式;最多显示9个启动器,标签上限为80字节,提示上限为32 KiB。面板会自动重新加载该文件,若配置无效或不支持会显示横幅提示。
recommend|decideinclude_defaults: false1旧版顶层运行文件中的字段仍可读取但已失效。请勿添加该字段。
actionsLose a runtime
运行时丢失
A pane died mid-work? The attempt is (no outcome needed), the task
projects to or . Do not delete the attempt; the trace is
the record.
lostfailedblocked面板在工作中途崩溃?尝试状态设为(无需outcome),任务状态投影为或。请勿删除尝试记录;跟踪记录是重要的历史凭证。
lostfailedblockedWhat NOT to do
禁止操作
- Don't renumber, rewrite, or delete attempts or events. Append.
- Don't put herdr pane/agent ids in task or attempt ids — they're
data, volatile by design.
locator - Don't claim without a mechanical receipt. Don't upgrade evidence after the fact without a new event explaining why.
verified - Don't encode task state from herdr's view of the world (pane alive ≠ work done). herdr is where, the contract is what is true.
- Don't mirror every internal agent/tool step; include work an operator needs to understand, steer, or verify.
- Don't hand-compute "% complete" — write per-attempt (
progress) and timestamps; analytics are queries over those.{"done": 3, "total": 7, "note": "..."}
- 不要重新编号、重写或删除尝试或事件记录。仅可追加。
- 不要将herdr面板/Agent ID放入任务或尝试ID中——这些属于数据,本质上是易变的。
locator - 不要在没有机械回执的情况下声称。若无新事件解释原因,不要事后升级证据层级。
verified - 不要从herdr对世界的视图编码任务状态(面板活跃≠工作完成)。herdr是执行位置,契约是真实状态。
- 不要镜像每个内部Agent/工具步骤;仅包含操作员需要理解、控制或验证的工作。
- 不要手动计算“完成百分比”——为每个尝试记录写入(
progress)和时间戳;分析是基于这些数据的查询。{"done": 3, "total": 7, "note": "..."}
Field reference
字段参考
The full schema is (Schema v3 section) in the dagr repo;
findings codes are listed there too. When names a code
you don't recognize, read its message — every finding carries the JSON
path of the offending field.
CONTRACT.mddagr check --json完整的模式定义位于dagr仓库中的(Schema v3章节);问题代码也列在其中。当返回你不熟悉的代码时,请阅读其消息——每个问题都会包含违规字段的JSON路径。
CONTRACT.mddagr check --json