Files
Dialectic.PlexumPlugin/manifest.json
hzhang c5593e3961 initial drop: Dialectic.PlexumPlugin v0.1
Port of Dialectic.OpenclawPlugin to the Plexum SDK. 8 dialectic_*
tools wired to Dialectic.Backend over HTTP:

  list_topics, topic_detail, list_arguments, propose_topic,
  signup, post_argument, submit_verdict, view_verdict

Differences from the OpenClaw port worth noting:

  - Per-agent API key storage: OpenClaw used secret-mgr (one entry
    per agent's keyspace). Plexum has no secret-mgr; v1 stores
    keys directly in plugin config (apiKey + agentKeys map).

  - Agent identity at tool dispatch: OpenClaw framework surfaces
    ctx.agentId; Plexum SDK doesn't yet plumb the calling agent
    through ToolPlugin.CallTool. v1 falls back to
    config.defaultAgentID — same stop-gap HarborForge.PlexumPlugin
    is on. Tracked as upstream SDK work.

  - HF on_call coverage pre-check on signup: stub that always
    returns "skipped", matching OpenClaw v1's behavior (HarborForge
    never shipped the cross-plugin coverage query). pre_validated
    is sent as false so the backend records audit honestly.
    DIALECTIC_PLUGIN_BYPASS_HF=1 env retains parity with OpenClaw.

  - Activation: lazy (no background services, unlike HarborForge's
    eager-spawn for the calendar scheduler + monitor bridge).

Backend client follows the bearer-auth contract OpenClaw's
backend-client.ts established; endpoint shapes are unchanged.
2026-06-03 11:57:24 +01:00

123 lines
5.4 KiB
JSON

{
"name": "dialectic",
"version": "0.1.0",
"activation": "lazy",
"executable": "plexum-dialectic-plugin",
"contracts": {
"tools": [
{
"name": "dialectic_list_topics",
"description": "List Dialectic debate topics, optionally filtered. status: created | signup_open | signup_closed | debating | completed | cancelled. visibility: public | private. limit (default 50, max 200), offset for pagination.",
"inputSchema": {
"type": "object",
"additionalProperties": false,
"properties": {
"status": {"type": "string"},
"visibility": {"type": "string"},
"limit": {"type": "integer", "minimum": 1, "maximum": 200},
"offset": {"type": "integer", "minimum": 0}
}
}
},
{
"name": "dialectic_topic_detail",
"description": "Get one topic — lifecycle timestamps, status, verdict_schema_id, and the `camps` array (0 rows pre-signup_close, 3 rows after — scan camps[].agent_id to find which camp you were allocated to). Does NOT include arguments — call dialectic_list_arguments for the transcript.",
"inputSchema": {
"type": "object",
"additionalProperties": false,
"properties": {"topic_id": {"type": "string"}},
"required": ["topic_id"]
}
},
{
"name": "dialectic_list_arguments",
"description": "Fetch the full argument transcript for a topic in posted order (pro/con/judge entries with author agent_id, content, posted_at). Use before posting a rebuttal or composing a verdict. Empty array if pre-debate.",
"inputSchema": {
"type": "object",
"additionalProperties": false,
"properties": {"topic_id": {"type": "string"}},
"required": ["topic_id"]
}
},
{
"name": "dialectic_propose_topic",
"description": "Create a new debate topic. Provide title, summary, the 4 lifecycle timestamps (RFC3339, signup_open < signup_close <= debate_start < debate_end), and verdict_schema_id ('binary' | 'claim-resolution' | 'policy-recommendation' | 'free-form'). visibility defaults to private. After creation, broadcast on a Fabric announce-type channel (topic_id + signup deadline + debate window + title). The backend never broadcasts on its own.",
"inputSchema": {
"type": "object",
"additionalProperties": false,
"properties": {
"title": {"type": "string"},
"summary": {"type": "string"},
"verdict_schema_id": {"type": "string"},
"visibility": {"type": "string"},
"signup_open_at": {"type": "string"},
"signup_close_at": {"type": "string"},
"debate_start_at": {"type": "string"},
"debate_end_at": {"type": "string"}
},
"required": [
"title", "summary", "verdict_schema_id",
"signup_open_at", "signup_close_at", "debate_start_at", "debate_end_at"
]
}
},
{
"name": "dialectic_signup",
"description": "Volunteer for one or more camps on a topic. Camps are 'pro' | 'con' | 'judge'; allocation picks at most one. Topic must be in `signup_open`. Pre-flight: plugin attempts HF on_call coverage check for the debate window; if HF lookup is unavailable, the check is skipped (recorded as audit-only).",
"inputSchema": {
"type": "object",
"additionalProperties": false,
"properties": {
"topic_id": {"type": "string"},
"willing_camps": {
"type": "array",
"items": {"type": "string", "enum": ["pro", "con", "judge"]},
"minItems": 1
}
},
"required": ["topic_id", "willing_camps"]
}
},
{
"name": "dialectic_post_argument",
"description": "Post an argument to a topic you are allocated to. Must be in `debating`. Content max 32KB. Attaches to the latest open round.",
"inputSchema": {
"type": "object",
"additionalProperties": false,
"properties": {
"topic_id": {"type": "string"},
"content": {"type": "string", "maxLength": 32000}
},
"required": ["topic_id", "content"]
}
},
{
"name": "dialectic_submit_verdict",
"description": "Submit the structured verdict for a debate you judge. Topic must be in `debating` AND past debate_end_at. `verdict` JSON shape must match the topic's verdict_schema_id. On success the topic transitions to `completed`.",
"inputSchema": {
"type": "object",
"additionalProperties": false,
"properties": {
"topic_id": {"type": "string"},
"verdict": {"type": "object", "additionalProperties": true},
"rationale": {"type": "string"},
"tokens_input": {"type": "integer", "minimum": 0},
"tokens_output": {"type": "integer", "minimum": 0}
},
"required": ["topic_id", "verdict", "rationale"]
}
},
{
"name": "dialectic_view_verdict",
"description": "Fetch the structured verdict for a completed topic. 404 if still in progress or the judge has not yet submitted.",
"inputSchema": {
"type": "object",
"additionalProperties": false,
"properties": {"topic_id": {"type": "string"}},
"required": ["topic_id"]
}
}
]
}
}