ledgerstep

package
v0.3.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 21, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

模板派发的共用段:取模板 → 算分支与基线 → 拼 prompt → 经注入的 Transport 派发 → 回链挂账 → 落 dispatched 快照。

职责:把「一张卡按某个模板派出去」这件事收口成一处,CLI 与 agentd 共用。 边界:

  • 不认领、不动卡状态——实现类派发在调用前自行 CAS 认领,环节派发不认领
  • 不做网络——传输经 Transport 注入,本文件不知道对端是 HTTP 还是别的什么
  • 不解析纪律块——只把角色名传下去,正文由 agentd 解析注入

工作流节点的通用执行体。节点行为由 ledger.NodeDef 的能力开关驱动, 依赖经函数字段注入,决策逻辑与副作用分离——单测覆盖决策,真机判据覆盖 真派发。

本地合并已于 2026-08-21 退役:合并改为普通派发节点(Dispatch+Verdict + finishing 纪律块),由 executor 在任务分支上完成,协调机不再执行 git 写操作。

回合计数:卡 × 环节粒度,从事件流推导,不存内存(spec §5——恢复 现场以账本为准,不信记忆)。规则:数该环节的 review_verdict 事件; 遇到带 human_reset_node=<环节> 的 comment 事件即清零(人工介入是 新基线,落事件注明)。

节点入口:把「跑一次工作流节点」收口成一个方法,CLI 与看板按钮共用同一份 装配逻辑。

边界:只做装配与分发,决策在 node.go 的 NodeStep;本文件不碰 HTTP、 不碰 cobra、不做输出编码——那些是各调用方自己的呈现层。

Package ledgerstep 工作流节点执行器:主会话(经 CLI)与看板按钮(经 API) 共用同一份节点决策与派发装配。 边界:无自有状态——回合计数从事件流推导,全部写入经 internal/ledger。

节点注入点的生产实现:节点派发走 dispatch 通道,裁决节点 wait 终态并取 报文;task 生命周期在此收口(裁决落账后 done 归档,不留孤儿)。

Index

Constants

View Source
const MaxRounds = 3

MaxRounds 默认封顶回合数,超限转「等人」。

Variables

This section is empty.

Functions

func CountRounds

func CountRounds(evs []ledger.Event, step string) int

CountRounds 数 step 自最近一次人工重置以来的裁决回合数。 evs 必须按 seq 升序(EventsFromAsc 的自然输出)。

Types

type Action

type Action string

Action 环节执行的结论。

const (
	ActionPass       Action = "pass"
	ActionContinue   Action = "continue"
	ActionNeedsHuman Action = "needs_human"
	// ActionDispatched 表示本节点只负责把任务派出去,不等结果(Verdict=false)。
	ActionDispatched Action = "dispatched"
)

type DispatchOpts

type DispatchOpts struct {
	Prompt, Branch, Target, Project, Executor, Model, PlanB64, PlanName, Base, ExistingBranch, Discipline string
	NewWorktree                                                                                           bool
}

DispatchOpts 是 Transport 的完整派发请求。PlanPath 已在 ViaTemplate 中 读成 PlanB64/PlanName;其余字段与 agentd 的派发协议一一对应。

type DispatchResult

type DispatchResult struct {
	Card            string `json:"card"`
	Task            string `json:"task"`
	Target          string `json:"target"`
	Branch          string `json:"branch"`
	Template        string `json:"template"`
	TemplateVersion int    `json:"template_version"`
	DisciplineName  string `json:"discipline_name"`
}

DispatchResult 是模板派发完成后的回显与审计信息。

type Dispatcher

type Dispatcher struct {
	St        *ledger.Store
	Transport Transport
	Actor     string
}

Dispatcher 持有模板派发需要的账本、传输和审计 actor。

func (*Dispatcher) ViaTemplate

func (d *Dispatcher) ViaTemplate(ctx context.Context, c ledger.Card, req TemplateDispatch) (DispatchResult, error)

ViaTemplate 按模板把一张卡派出去。

参数:c 卡;req 模板名、目标机、可选 plan 路径与纪律块角色名覆盖。 返回:派发结果(含 task id、分支、模板版本、纪律块角色名)。

注意:不含认领语义。实现类派发在调用前自行 CAS 认领;环节派发 (审阅/合并)刻意不认领——它们是待审阅卡上的动作,认领会把卡拉回进行中。

req.PlanPath 按调用方进程的 CWD 解析。agentd 一侧永远传空串: 浏览器里没有 plan 文件,实现类派发也不从界面走。

type Finding

type Finding struct {
	Severity string `json:"severity"`
	Summary  string `json:"summary"`
	File     string `json:"file,omitempty"`
}

Finding 审阅发现项。

type NodeStep

type NodeStep struct {
	St   *ledger.Store
	Node ledger.NodeDef
	// Dispatch 按节点配置把卡派出去,返回目标机与 task id。
	Dispatch func(ctx context.Context, card ledger.Card, node ledger.NodeDef) (target, taskID string, err error)
	// Await 等该 task 跑到回合终态并取回最终报文。只在 Node.Verdict 时调用。
	Await func(ctx context.Context, target, taskID string) (message string, err error)
}

NodeStep 通用节点执行体:一个节点该怎么跑,完全由 Node 上的能力开关决定, 本类型不认识「审阅」「合并」这些名字。

依赖经函数字段注入(Dispatch/Await),决策逻辑与副作用分离——单测覆盖 决策,真机判据覆盖副作用。

func (*NodeStep) RunOnce

func (n *NodeStep) RunOnce(ctx context.Context, cardID string) (Outcome, error)

RunOnce 跑一次本节点。

参数:cardID 卡。 返回:Outcome(下一步动作 + 裁决 + 理由);只有「本节点根本不该被执行」 (纯人工列)和账本写失败才返回 error,其余异常一律转成 needs_human 并留痕。

阻塞行为:Node.Verdict 为真时会阻塞到被派出去的 task 跑到回合终态——几分钟 到几十分钟,executor 挂在 waiting_answer 时更久。调用方自行决定要不要放 goroutine 里跑。

type Outcome

type Outcome struct {
	Action  Action
	Verdict Verdict
	Reason  string
}

Outcome 环节单次执行结果。

type StepRunner

type StepRunner struct {
	St         *ledger.Store
	Dispatcher *Dispatcher
	// Clients 按 target 名取一个已装配好的 agentd 客户端。
	//
	// why 这里要的是客户端而不是 (addr, token):relay 形态的机器根本没有 addr,
	// 拿地址自己 client.New 对它们恒失败(会退化成一个没有 Host 的 URL)。
	// 选路归 agentd 的 target 客户端池管,本包只消费。
	Clients func(target string) (*client.Client, error)
	// Target 覆盖节点/模板里的目标机;空则用节点覆盖或模板的 target。
	Target string
	// Extra 本次执行的临时补充说明,透传进 prompt 的第三段;可为空。
	Extra string
}

StepRunner 节点执行的装配器。依赖全部显式注入,调用方各填各的。

本地仓路径与主线名已随本地合并退役一并删除:合并现在是普通派发节点, 由 executor 在任务分支上完成,协调机不再执行任何 git 写操作。

func (*StepRunner) Run

func (r *StepRunner) Run(ctx context.Context, cardID, nodeName string) (Outcome, error)

Run 跑一次节点。

参数:cardID 卡;nodeName 节点名(= 看板的列名),从卡钉住的工作流版本里查。 返回:Outcome;节点不存在、没有 Dispatch 能力或执行内部失败时返回错误。

阻塞行为:节点开了 Verdict 时会阻塞到被派出去的 task 跑到回合终态 (几分钟到几十分钟,executor 挂在 waiting_answer 时更久)。调用方要么 自己在 goroutine 里跑(agentd 就是这么做的),要么接受前台阻塞(CLI)。

type TemplateDispatch

type TemplateDispatch struct {
	Template           string
	Target             string
	PlanPath           string
	DisciplineOverride string
	// ExecutorOverride / ModelOverride 是节点对模板的单字段覆盖;空 = 用模板的。
	ExecutorOverride string
	ModelOverride    string
	// CarryCardContext 为真时把卡上下文段拼进 prompt(来自节点的同名开关)。
	CarryCardContext bool
	// Extra 是本次派发的临时补充说明,可为空。
	Extra string
}

TemplateDispatch 描述一次按模板派发:模板、目标机、可选 plan 与纪律角色覆盖。

type Transport

type Transport func(ctx context.Context, opts DispatchOpts) (taskID string, err error)

Transport 是注入的派发传输。返回 agentd 生成的 task id;实现不关心传输协议。

type Verdict

type Verdict struct {
	Pass     bool      `json:"pass"`
	Findings []Finding `json:"findings"`
	Notes    string    `json:"notes,omitempty"`
	Raw      string    `json:"-"`
}

Verdict 解析后的裁决。

func ParseVerdict

func ParseVerdict(message string) (Verdict, error)

ParseVerdict 从审阅报文提取最后一个 handoff-verdict block 并解析。 解析失败不猜(调用方转「等人」,原文落 timeline)——spec §5 契约。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL