local F = require("flow_dsl")
local B = require("bp_dsl")
local worktree_merge_step = F.step({
agent = "worktree-merge",
input = F.p("$.d.merge"),
out = F.p("$.merge"),
})
local worktree_merge_gate = F.branch({
cond = F.p('$.merge.parts["verdict"]'):eq("BLOCKED"),
on_true = F.assign({ at = F.p("$.halted_at"), value = F.lit("worktree-merge") }),
on_false = F.assign({ at = F.p("$.phase_b_complete"), value = F.lit(true) }),
})
local committer_step = F.step({
agent = "committer",
input = F.p("$.d.commit"),
out = F.p("$.commit"),
})
local committer_gate = F.branch({
cond = F.p('$.commit.parts["verdict"]'):eq("BLOCKED"),
on_true = F.assign({ at = F.p("$.halted_at"), value = F.lit("committer") }),
on_false = F.seq({ worktree_merge_step, worktree_merge_gate }),
})
local qgate_step = F.step({
agent = "quality-gate",
input = F.p("$.d.qgate"),
out = F.p("$.qgate_verdict"),
})
local build_resolver_step = F.step({
agent = "build-resolver",
input = F.p("$.qgate_verdict"),
out = F.p("$.resolve"),
})
local qgate_rerun_step = F.step({
agent = "quality-gate",
input = F.p("$.d.qgate"),
out = F.p("$.qgate_verdict"),
})
local qgate_loop = F.loop_({
counter = F.p("$.qg_n"),
cond = F.p("$.qg_n"):lt(2):And(F.p('$.qgate_verdict.parts["verdict"]'):eq("BLOCKED")),
max = 3,
body = F.seq({ build_resolver_step, qgate_rerun_step }),
})
local qgate_final_gate = F.branch({
cond = F.p('$.qgate_verdict.parts["verdict"]'):eq("BLOCKED"),
on_true = F.assign({ at = F.p("$.halted_at"), value = F.lit("quality-gate") }),
on_false = F.seq({ committer_step, committer_gate }),
})
local qcode_step = F.step({
agent = "quality-coding",
input = F.p("$.d.qcode"),
out = F.p("$.qcode"),
})
local qcode_gate = F.branch({
cond = F.p('$.qcode.parts["verdict"]'):eq("BLOCKED"),
on_true = F.assign({ at = F.p("$.halted_at"), value = F.lit("quality-coding") }),
on_false = F.seq({ qgate_step, qgate_loop, qgate_final_gate }),
})
local impl_step = F.step({
agent = "impl-lead",
input = F.p("$.d.impl"),
out = F.p("$.impl"),
})
local impl_gate = F.branch({
cond = F.p('$.impl.parts["verdict"]'):eq("BLOCKED"),
on_true = F.assign({ at = F.p("$.halted_at"), value = F.lit("impl-lead") }),
on_false = F.seq({ qcode_step, qcode_gate }),
})
local context_step = F.step({
agent = "context-librarian",
input = F.p("$.d.context"),
out = F.p("$.context"),
})
local context_gate = F.branch({
cond = F.p('$.context.parts["verdict"]'):eq("BLOCKED"),
on_true = F.assign({ at = F.p("$.halted_at"), value = F.lit("context-librarian") }),
on_false = F.seq({ impl_step, impl_gate }),
})
local workspace_step = F.step({
agent = "workspace-setup",
input = F.p("$.d.workspace_setup"),
out = F.p("$.workspace"),
})
local workspace_gate = F.branch({
cond = F.p('$.workspace.parts["verdict"]'):eq("BLOCKED"),
on_true = F.assign({ at = F.p("$.halted_at"), value = F.lit("workspace-setup") }),
on_false = F.seq({ context_step, context_gate }),
})
local topic_step = F.step({
agent = "topic-setup",
input = F.p("$.d.topic_setup"),
out = F.p("$.topic"),
})
local topic_gate = F.branch({
cond = F.p('$.topic.parts["verdict"]'):eq("BLOCKED"),
on_true = F.assign({ at = F.p("$.halted_at"), value = F.lit("topic-setup") }),
on_false = F.seq({ workspace_step, workspace_gate }),
})
local flow = F.seq({ topic_step, topic_gate })
local agents = {
B.agent({ md = "topic-setup.md", spec = { operator_ref = "main-ai" } }),
B.agent({ md = "workspace-setup.md", spec = { operator_ref = "main-ai" } }),
B.agent({ md = "context-librarian.md", spec = { operator_ref = "main-ai" } }),
B.agent({ md = "impl-lead.md", spec = { operator_ref = "main-ai" } }),
B.agent({ md = "quality-coding.md", spec = { operator_ref = "main-ai" } }),
B.agent({
md = "quality-gate.md",
verdict = { channel = "part", values = { "PASS", "BLOCKED" } },
spec = { operator_ref = "main-ai" },
}),
B.agent({ md = "committer.md", spec = { operator_ref = "main-ai" } }),
B.agent({ md = "worktree-merge.md", spec = { operator_ref = "main-ai" } }),
B.agent({ md = "build-resolver.md", spec = { operator_ref = "main-ai" } }),
}
local operators = {
{
name = "main-ai",
display_name = "Main AI (Coding Orch dispatcher)",
kind = "main_ai",
spec = {},
},
}
return {
id = "coding-orch-phase-b",
flow = flow,
agents = agents,
strategy = { strict_refs = true, strict_kind = true },
metadata = {
default_run_ttl_secs = 5400,
description = "Real-world coding-pipeline shape: nine verdict-gated stages in sequence with a bounded fix-and-regate retry loop around the quality gate. Callers seed per-stage directives under init_ctx.d and the retry counter qg_n=0. The quality-gate agent declares a verdict contract (channel=part, values=[PASS, BLOCKED]) so compile-time cond lint and submit-time gating protect the loop shape.",
},
operators = operators,
}