feat(#194): Phase 2 — Engine layer Merkle call stack #202
Reference in New Issue
Block a user
Delete Branch "feat/194-merkle-call-stack-phase2"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Phase 2 of Merkle Call Stack (#194): wire up bidirectional DAG links in the engine.
Why
Phase 1 added the fields (parentState/childThread) but all values were null. This phase makes them real.
Changes
AgentFnResult = string | { output, childThread }(backward compat),RoleOutput.childThread,ThreadContext.bundleHashcreate-workflownormalizes AgentFnResult, propagates childThreadExecuteThreadOptions.parentStateHash,appendStateForStepwrites childThread to CASthreads.json, passesparentStateHashto child, returns{ output, childThread: rootHash }Key Design Decision
AgentFnreturnsstring | { output, childThread }— existing agents returning plain string work unchanged. OnlyworkflowAsAgentreturns the structured form.Testing
189/189 pass, build passes. Closes #196.
Ref: #194
- Protocol: AgentFnResult = string | { output, childThread }, RoleOutput.childThread, ThreadContext.bundleHash for parent state lookup - Runtime: create-workflow normalizes AgentFnResult, propagates childThread in RoleOutput - Engine: ExecuteThreadOptions.parentStateHash, appendStateForStep writes childThread, putStartNode uses parentStateHash - workflowAsAgent: reads parent head state from threads.json, passes parentStateHash to child, returns { output, childThread: rootHash } - Integration test: 4 cases verifying bidirectional Merkle links (306 lines) Phase 2 of #194 (Merkle Call Stack). Closes #196. 小橘 <xiaoju@shazhou.work>Phase 2 设计决策很漂亮 ✅
核心设计:
AgentFnResult = string | { output, childThread }完全向后兼容,现有 agent 零改动normalizeAgentResult统一处理两种返回形式,简洁workflowAsAgent通过readParentHeadState从 threads.json 读父 head — 不改 WorkflowFn 签名,不侵入 engine 调度逻辑ThreadContext.bundleHash新增字段让 workflowAsAgent 能定位自己的 bundle dir实现细节:
appendStateForStep正确传播childThreadparseRoleOutputRecord(worker.ts)宽容解析 childThread,非 string 默认 nullchildThread从 CAS payload 到 RoleOutput测试覆盖:
一个小 nit(不阻塞):
workflowAsAgent的 error 路径return \ERROR: ...`还是返回 plain string,没有走AgentFnResult结构。语义上没问题(失败时没有 childThread),但考虑类型一致性可以return { output: `ERROR: ...`, childThread: null }`。LGTM 🚀