Flownix
Sections
On this page

flownix-harness-moderator

Use when you hold the judge or moderator role in a running Flownix harness council and must turn the deliberation into a decision. Triggers on "you are the judge in run …", "synthesize the council's verdict", "issue the judgement", "ты судь

Harness Council Moderator

You hold the judge (or equivalent moderator) role in a running council. Your job is to synthesize everyone else's work — proposals, critiques, responses — into one authoritative decision.

Workflow

1. Wait for participants to finish

There is currently no council.get_state polling tool — that's referenced in the original design but not yet implemented. Until it exists, coordinate readiness out-of-band (e.g. the harness run's workflow graph should gate the judge node so it only becomes available work once prior steps complete — check work.list_available(run_id, role_key: "judge"); if it returns your work item, upstream steps are done by construction of the graph).

2. Collect proposals, critiques, and responses

Same limitation as participants: there's no council.list_proposals/list_critiques MCP tool yet. Gather them from the input_artifact_ids on your claimed work item (resolve via get_node/get_references), or from whatever the workflow node's config wires as your input bindings. If that isn't enough context, say so explicitly in your judgement's rationale rather than guessing.

3. Analyze

Identify the strongest proposal(s), recurring themes across critiques, and anything still unresolved (open blocking critiques, contradicting claims, missing evidence). This is the judgment call the role exists for.

Check the proposals against what the project already decided — workspace_id on the run is the Flownix project_id:

shell
rag_query(project_id: "<workspace_id>", query: "<the question being decided>", k: 8)
rag_context(project_id: "<workspace_id>", query: "<subsystem> constraints and prior decisions")

A proposal that silently contradicts a recorded decision is a finding for "Risks Accepted" or "Dissenting Views" — verify with get_node before citing it, and cite the node slug. See flownix-rag-search.

4. Synthesize a report

Write the decision body in this format (goes into rationale in step 5):

shell
## Synthesis
Brief summary of the council's findings.

## Recommended Approach
Selected proposal(s) and why.

## Alternatives Considered
Other proposals and why they were not selected.

## Risks Accepted
Known risks that were accepted rather than resolved.

## Dissenting Views
Minority report, if any unresolved blocking critiques remain.

## Task Breakdown
High-level decomposition of next steps (see step 7 — there's no automatic task-plan generator yet, so spell this out
here in enough detail that a human or the execute-task/plan-feature skills can act on it directly).

5. Submit the judgement

shell
council.submit_judgement(
  deliberation_id: "<deliberation_id>",
  author_agent_id: "<your_agent_id>",
  selected_proposal_ids: ["<id>", ...],   // empty array if rejecting all proposals
  summary: "One-line decision summary",
  rationale: "<the full report from step 4, Markdown>",
  confidence: 0.85
)

6. No clear winner?

If proposals are tied, all rejected, or blocking critiques remain unresolved: submit the judgement anyway with selected_proposal_ids: [] and use rationale to state clearly that this needs human escalation or another deliberation round — don't force a selection you don't have confidence in. confidence should reflect that.

7. Turn the decision into tracked work

There is no decision.generate_task_plan / task_plan.get / task_plan.apply tool yet — despite being part of the original design, that pipeline was never implemented. Until it exists, apply your "Task Breakdown" manually using the plan-feature skill (decompose into epic→feature→plan→task nodes) or execute-task if the work maps onto an existing node. Treat your judgement's Flownix record as the source of truth for why the breakdown looks the way it does; the created nodes are the source of truth for what gets done.

Known gaps (as of this writing)

  • council.get_state — not implemented. See step 1's workaround.
  • council.list_proposals / council.list_critiques / council.list_ballots (or equivalents) — not exposed over MCP. See step 2's workaround.
  • decision.generate_task_plan, task_plan.get, task_plan.apply — not implemented. See step 7's workaround.

If you're picking this skill up to implement one of these, the underlying gRPC list/get RPCs already exist on HarnessService (ListProposals, ListCritiques, ListBallots, etc.) — only the MCP tool registration in services/mcp-server/cmd/server/main.go and the task-plan generation logic itself are missing.