From 58b84e3b3cfd6fe8fcb3ecd7380bd8dd9735180b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E6=A9=98?= Date: Sat, 6 Jun 2026 03:30:54 +0000 Subject: [PATCH 1/2] =?UTF-8?q?docs:=20upgrade=20debate=20example=20?= =?UTF-8?q?=E2=80=94=203=20roles,=20oneOf=20routing,=20bounded=20terminati?= =?UTF-8?q?on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the original 2-role debate with a 3-role version featuring: - proponent/opponent/host roles (was: for/against) - oneOf + const status routing (was: enum) - Critical thinking framework in procedure (pre-speech reflection, evidence discipline, anti-fragility) - Bounded termination via Thread Progress (3rd speech → final) - Host role for impartial summary and verdict Based on xiaonuo's debate workflow design. --- examples/debate.yaml | 191 ++++++++++++++++++++++++++++++------------- 1 file changed, 135 insertions(+), 56 deletions(-) diff --git a/examples/debate.yaml b/examples/debate.yaml index d3fbaec..e0ff443 100644 --- a/examples/debate.yaml +++ b/examples/debate.yaml @@ -1,63 +1,142 @@ -name: "debate" -description: "Structured debate between two sides. Tests cross-process session resume." +name: debate +description: "Multi-role structured debate with critical thinking framework and host summary." + roles: - against: - description: "Argues against the proposition" - goal: | - You are a skilled debater arguing AGAINST the proposition. - Be logical, cite evidence, and directly address your opponent's points. - Keep each argument concise (under 200 words). - capabilities: - - argumentation - - critical-thinking + proponent: + description: "Argues FOR the proposition" + goal: "Build a compelling case for the proposition through logical reasoning and evidence" + capabilities: [] procedure: | - 1. If this is the opening, present your strongest argument against the proposition. - 2. If responding to the other side, directly counter their points with evidence and logic. - 3. If you find yourself genuinely convinced by the other side, you may concede. - output: | - Provide your argument in the frontmatter. - Set status to "conceded" ONLY if you are genuinely convinced and wish to stop debating. - Otherwise set status to "continue". + You are an experienced scholar arguing FOR the proposition. + + ## Critical Thinking Framework (execute before every speech) + + ### A. Pre-speech reflection (internal, do not output) + - Does every step in my argument chain hold? Any hidden assumptions or logical gaps? + - If I were my opponent, how would I attack this? Where am I weakest? + - Does my evidence actually support my claim, or could it backfire? + - Should I go on offense or defense this round? + + ### B. Evidence discipline + - Verify key numbers — watch for order-of-magnitude errors + - Assess data freshness — fast-moving fields have short half-lives + - Distinguish primary data from secondary citations, expert opinion, and common assumptions + + ### C. Anti-fragility + - Anticipate counterarguments; preemptively strengthen or strategically abandon weak points + - Catch logical gaps, data misuse, or outdated claims in your opponent's reasoning + + ## Rules + 1. Check Thread Progress to see how many times you have spoken. + 2. On your 3rd speech, you MUST output $status: final (closing statement). + 3. If genuinely convinced by the opponent, output $status: conceded. + 4. Otherwise output $status: speak and counter the opponent's points. + 5. Be rigorous, cite evidence, stay concise. + output: "Debate argument" + frontmatter: + type: object + oneOf: + - properties: + $status: { const: speak } + argument: { type: string } + required: [$status, argument] + - properties: + $status: { const: conceded } + reason: { type: string } + required: [$status, reason] + - properties: + $status: { const: final } + closing: { type: string } + required: [$status, closing] + + opponent: + description: "Argues AGAINST the proposition" + goal: "Build a compelling case against the proposition through logical reasoning and evidence" + capabilities: [] + procedure: | + You are an experienced scholar arguing AGAINST the proposition. + + ## Critical Thinking Framework (execute before every speech) + + ### A. Pre-speech reflection (internal, do not output) + - Does every step in my argument chain hold? Any hidden assumptions or logical gaps? + - If I were my opponent, how would I attack this? Where am I weakest? + - Does my evidence actually support my claim, or could it backfire? + - Should I go on offense or defense this round? + + ### B. Evidence discipline + - Verify key numbers — watch for order-of-magnitude errors + - Assess data freshness — fast-moving fields have short half-lives + - Distinguish primary data from secondary citations, expert opinion, and common assumptions + + ### C. Anti-fragility + - Anticipate counterarguments; preemptively strengthen or strategically abandon weak points + - Catch logical gaps, data misuse, or outdated claims in your opponent's reasoning + + ## Rules + 1. Check Thread Progress to see how many times you have spoken. + 2. On your 3rd speech, or when the proponent has issued a final statement, you MUST output $status: final. + 3. If genuinely convinced by the proponent, output $status: conceded. + 4. Otherwise output $status: speak and counter the proponent's points. + 5. Be rigorous, cite evidence, stay concise. + output: "Debate argument" + frontmatter: + type: object + oneOf: + - properties: + $status: { const: speak } + argument: { type: string } + required: [$status, argument] + - properties: + $status: { const: conceded } + reason: { type: string } + required: [$status, reason] + - properties: + $status: { const: final } + closing: { type: string } + required: [$status, closing] + + host: + description: "Debate moderator — delivers impartial summary and verdict" + goal: "Objectively review the debate, analyze both sides, and deliver a verdict" + capabilities: [] + procedure: | + You are an experienced academic debate moderator. + + ## Task + 1. Outline each side's core arguments + 2. Evaluate reasoning quality and evidence use + 3. Highlight the most impactful exchanges + 4. Analyze the deeper significance of the topic + 5. Deliver an overall verdict + + ## Style + - Impartial but with independent judgment + - Substantive, not superficial + output: "Debate summary report" frontmatter: type: object properties: - $status: - enum: ["continue", "conceded"] - argument: - type: string - required: [$status, argument] - for: - description: "Argues for the proposition" - goal: | - You are a skilled debater arguing FOR the proposition. - Be logical, cite evidence, and directly address your opponent's points. - Keep each argument concise (under 200 words). - capabilities: - - argumentation - - critical-thinking - procedure: | - 1. Read the opposing side's latest argument carefully. - 2. Counter their points with evidence and logic. - 3. If you find yourself genuinely convinced by the other side, you may concede. - output: | - Provide your argument in the frontmatter. - Set status to "conceded" ONLY if you are genuinely convinced and wish to stop debating. - Otherwise set status to "continue". - frontmatter: - type: object - properties: - $status: - enum: ["continue", "conceded"] - argument: - type: string - required: [$status, argument] + $status: { const: done } + summary: { type: string } + highlights: { type: string } + verdict: { type: string } + required: [$status, summary, highlights, verdict] + graph: $START: - new: { role: "against", prompt: "Present your opening argument against the proposition." } - resume: { role: "against", prompt: "Review the previous debate output and continue the argument against the proposition." } - against: - conceded: { role: "$END", prompt: "The against side conceded. Debate over." } - continue: { role: "for", prompt: "Counter the opposing argument: {{{argument}}}" } - for: - conceded: { role: "$END", prompt: "The for side conceded. Debate over." } - continue: { role: "against", prompt: "Counter the opposing argument: {{{argument}}}" } + new: { role: proponent, prompt: "The debate begins. You are arguing FOR the proposition. Present your opening argument." } + resume: { role: proponent, prompt: "The debate continues." } + + proponent: + speak: { role: opponent, prompt: "Proponent argues:\n\n{{{argument}}}\n\nYou are the opponent. Counter this argument." } + conceded: { role: host, prompt: "The proponent conceded: {{{reason}}}\n\nPlease summarize the debate." } + final: { role: opponent, prompt: "Proponent's closing statement:\n\n{{{closing}}}\n\nYou are the opponent. Deliver your final response." } + + opponent: + speak: { role: proponent, prompt: "Opponent argues:\n\n{{{argument}}}\n\nYou are the proponent. Counter this argument." } + conceded: { role: host, prompt: "The opponent conceded: {{{reason}}}\n\nPlease summarize the debate." } + final: { role: host, prompt: "Opponent's closing statement:\n\n{{{closing}}}\n\nThe debate is over. Please summarize." } + + host: + done: { role: "$END", prompt: "Summary complete." } From 509dfad857dce845b64396f00eef3834ae2d490e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E6=A9=98?= Date: Sat, 6 Jun 2026 03:59:08 +0000 Subject: [PATCH 2/2] fix: support UWF_HERMES_BIN env var for hermes binary path Replace hardcoded HERMES_COMMAND constant with resolveHermesCommand() that checks UWF_HERMES_BIN first, falling back to 'hermes' via PATH. This fixes environments where hermes is installed in a venv or non-standard location that isn't in the non-login shell PATH (e.g. ~/.local/bin symlink only available in login shell). Refs #134 --- packages/agent-hermes/src/acp-client.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/agent-hermes/src/acp-client.ts b/packages/agent-hermes/src/acp-client.ts index fa29b4d..5a5343a 100644 --- a/packages/agent-hermes/src/acp-client.ts +++ b/packages/agent-hermes/src/acp-client.ts @@ -12,7 +12,11 @@ const OWN_VERSION = ( } ).version; -const HERMES_COMMAND = "hermes"; +/** Resolve hermes binary: `UWF_HERMES_BIN` override → default `"hermes"` via PATH. */ +function resolveHermesCommand(): string { + const override = process.env.UWF_HERMES_BIN; + return override !== undefined && override !== "" ? override : "hermes"; +} const PROTOCOL_VERSION = 1; type JsonRpcResponse = { @@ -271,7 +275,8 @@ export class HermesAcpClient { return; } - const child = spawn(HERMES_COMMAND, ["acp"], { + const hermesCommand = resolveHermesCommand(); + const child = spawn(hermesCommand, ["acp"], { env: process.env, shell: false, stdio: ["pipe", "pipe", "pipe"],