local ctx = _CTX
if type(ctx) ~= "table" then
error("committer: _CTX must be a table")
end
local verdicts = ctx.verdicts
if type(verdicts) ~= "table" then
error("committer: ctx.verdicts must be an array (Fanout join=all output)")
end
local deny_reasons = {}
local verdicts_summary = {}
for _, branch_ctx in ipairs(verdicts) do
if type(branch_ctx) ~= "table" or type(branch_ctx.verdict) ~= "table" then
error("committer: verdict branch shape invalid (expected {verdict={axis,outcome}})")
end
local v = branch_ctx.verdict
local axis = tostring(v.axis or error("committer: verdict.axis missing"))
local outcome = v.outcome
if type(outcome) ~= "table" then
error("committer: verdict.outcome missing or not table (axis=" .. axis .. ")")
end
if outcome.Deny ~= nil then
local reason = tostring(outcome.Deny.reason or error("committer: Deny.reason missing"))
table.insert(deny_reasons, axis .. ": " .. reason)
table.insert(verdicts_summary, { axis = axis, status = "deny", reason = reason })
elseif outcome.Pass ~= nil then
local evidence = tostring(outcome.Pass.evidence or "")
table.insert(verdicts_summary, { axis = axis, status = "pass", evidence = evidence })
else
error("committer: verdict.outcome must be Pass or Deny (axis=" .. axis .. ")")
end
end
local patch = ctx.patch
if type(patch) ~= "table" then
error("committer: ctx.patch must be a table (carried from patch-spawner step)")
end
local rationale = tostring(patch.rationale or error("committer: patch.rationale missing"))
local bump = tostring(patch.bump or error("committer: patch.bump missing"))
if #deny_reasons == 0 then
local applied = ctx.applied
if type(applied) ~= "table" then
error("committer: ctx.applied must be a table for committed=true case")
end
local new_hash = tostring(applied.new_hash or error("committer: applied.new_hash missing"))
local new_bp_yaml = tostring(applied.new_bp_yaml or error("committer: applied.new_bp_yaml missing"))
local new_bp_json = applied.new_bp_json
if type(new_bp_json) ~= "table" then
error("committer: applied.new_bp_json must be a table")
end
return {
value = {
committed = true,
new_version = new_hash,
new_bp_yaml = new_bp_yaml,
new_bp_json = new_bp_json,
bump = bump,
rationale = rationale,
verdicts_summary = verdicts_summary,
},
ok = true,
}
else
return {
value = {
committed = false,
reasons = deny_reasons,
rationale = rationale,
verdicts_summary = verdicts_summary,
},
ok = true,
}
end