Kanban Governance Board — Centralismo Democratico
The 7-column governance kanban for multi-agent proposal lifecycle management: draft, submitted, debating, chancela, congress_approved, vetoed, promoted, with ELO-rated debate rounds and congress sessions.
Kanban Governance Board
The Kanban Governance Board is the visual decision-making surface of the co-fita-harness. Implemented as a "Centralismo Democratico" system, it provides a 7-column Kanban interface where proposals from both human and AI agents flow through a structured lifecycle: from draft creation, through adversarial debate with ELO rating, to final human approval (the "Chancela") or veto. The system enables collaborative workspace evolution through a governance engine backed by SQLAlchemy, a FastAPI route layer, and a vanilla JS drag-and-drop frontend.
Philosophy
The governance system embodies the Co-Fita principle that protocols are dialectical instruments -- they exist to be challenged and refined. Rather than having the human author dictate all workspace configuration, agents can propose changes (new skills, rules, workflows, tools, MCP servers, model configs) and defend them in structured debate. The human principal retains final authority through the "Chancela" (Portuguese for "chancellor's seal"), but the ELO rating system ensures that well-reasoned proposals accumulate credibility over time.
This is not a toy. Proposals can modify the agent's own behavioral rules, tool access, and prompt configuration. The governance system is how the workspace self-evolves.
The 7 Columns
graph LR
D["Draft"] --> S["Submitted"]
S --> DB["Debating"]
DB --> CC["Chancela"]
CC --> AP["Approved"]
CC --> VT["Vetoed"]
AP --> PR["Promoted"]
VT --> ARCH["Archived"]
style D fill:#3e4451,stroke:#5c6370,color:#abb2bf
style S fill:#2c6fbb,stroke:#3d85c6,color:#fff
style DB fill:#d19a66,stroke:#e5c07b,color:#282c34
style CC fill:#e06c75,stroke:#e06c75,color:#fff
style AP fill:#61afef,stroke:#56b6c2,color:#282c34
style VT fill:#be5046,stroke:#e06c75,color:#fff
style PR fill:#98c379,stroke:#56b6c2,color:#282c34
| # | Column | ID | Purpose |
|---|---|---|---|
| 1 | Draft | draft | Initial proposal state. Created by any user or agent. Not yet visible to congress. |
| 2 | Submitted | submitted | Proposal is ready for review. Added to the congress queue. submitted_at timestamp recorded. |
| 3 | Debating | debating | Active adversarial debate rounds. ELO rating updates with each round. |
| 4 | Chancela | awaiting_chancela | Passed debate. Awaiting human approval or veto. Visually highlighted with red glow. |
| 5 | Approved | congress_approved | Congress has approved the proposal. Awaiting final Chancela. |
| 6 | Vetoed | vetoed | Rejected by Chancela or during congress. Terminal state. |
| 7 | Promoted | promoted | Fully approved and promoted. The proposal is now active policy. |
The archived status exists in the backend enum but has no dedicated column in the UI -- archived proposals are hidden from the board.
Proposal Lifecycle
stateDiagram-v2
[*] --> Draft: create_proposal()
Draft --> Submitted: update_status(SUBMITTED)
Submitted --> Debating: update_status(DEBATING)
Debating --> Debating: record_debate_round()
Debating --> CongressApproved: congress close(resolutions)
Debating --> Vetoed: congress close(resolutions)
Submitted --> CongressApproved: congress close(resolutions)
CongressApproved --> AwaitingChancela: update_status(AWAITING_CHANCELA)
AwaitingChancela --> Promoted: chancela_proposal(approved=True)
AwaitingChancela --> Vetoed: chancela_proposal(approved=False)
CongressApproved --> Vetoed: chancela_proposal(approved=False)
Draft --> Archived: update_status(ARCHIVED)
Vetoed --> Archived: update_status(ARCHIVED)
Step 1: Creation
Any authenticated user (or agent via API token) creates a proposal with:
- Category: What kind of change (skill, workflow, rule, hook, integration, tool, mcp, model_config, harness_config, prompt)
- Name: Human-readable title
- Content: The actual proposal detail
- Rationale: Why this change is needed
- Origin: Where the idea came from (failure_observation, dead_end_analysis, performance_insight, reflection, human_directive, congress_debate)
- Failure context (optional): What went wrong that prompted this
- Current artifact (optional): The existing artifact being proposed for change
Step 2: Submission
The proposer (or an admin) moves the proposal to submitted. This records submitted_at and makes it visible to the congress system.
Step 3: Debate
Proposals enter adversarial debate rounds. Each round:
- The proposal is pitted against an opponent (another proposal or a baseline)
- A judge (typically the local model, but extensible) evaluates which is stronger
- ELO ratings are updated using the standard chess formula:
expected = 1 / (1 + 10^((opponent_elo - proposal_elo) / 400))
actual = 1.0 if won, 0.0 if lost
proposal_elo += K * (actual - expected)
Where K = 32 (standard ELO coefficient).
Each debate round is logged with timestamp, outcome, ELO after, opponent ELO, reason, and judge. The debate_log JSON column stores the full history.
Step 4: Congress
The CentralCommittee convenes a congress session:
- Convene: Gather all proposals in
submittedordebatingstatus. Record which agents are present. - Deliberate: Agents discuss and vote on proposals (resolution data stored in congress session).
- Close: Congress records resolutions and marks the session as concluded.
Congress can approve or veto proposals. Approved proposals move to congress_approved; vetoed ones move to vetoed.
Step 5: Chancela
The human principal reviews proposals that passed congress. This is the ultimate authority gate:
- Approve: Proposal moves to
promoted. It becomes active policy. - Veto: Proposal moves to
vetoed. It is rejected.
The chancela_proposal method records approved_at, approved_by, and promoted_at timestamps.
Step 6: Promotion
Promoted proposals are the living policy of the workspace. Their content can be:
- New MCP tool configurations
- Modified agent rules or prompts
- Updated model routing policies
- New skills or workflows
- Changed governance parameters
Proposal Categories
| Category | ID | Typical Content |
|---|---|---|
| Skill | skill | New reusable skill definition |
| Workflow | workflow | Multi-step process improvement |
| Rule | rule | Behavioral constraint or directive |
| Hook | hook | PreToolUse/PostToolUse enforcement |
| Integration | integration | External service connection |
| Tool | tool | New agent tool or modification |
| MCP | mcp | MCP server configuration |
| Model Config | model_config | Endpoint, routing, or fallback changes |
| Harness Config | harness_config | Dashboard or system-level settings |
| Prompt | prompt | System prompt modifications |
Proposal Origins
| Origin | ID | When Used |
|---|---|---|
| Failure Observation | failure_observation | Agent observed a failure and proposes a fix |
| Dead End Analysis | dead_end_analysis | Agent hit a dead end and proposes an alternative path |
| Performance Insight | performance_insight | Agent identified a performance improvement |
| Reflection | reflection | Agent self-reflects and proposes behavioral changes |
| Human Directive | human_directive | Human explicitly requested a change |
| Congress Debate | congress_debate | Emerged from congress discussion |
ELO Rating System
Each proposal starts with an ELO of 1200 (standard chess baseline). Debate rounds adjust this rating:
| ELO Range | Interpretation |
|---|---|
| < 1000 | Weak proposal, consistently losing debates |
| 1000-1200 | Below average, needs significant improvement |
| 1200 | Baseline (starting value) |
| 1200-1400 | Above average, winning more than losing |
| 1400-1600 | Strong proposal, well-reasoned |
| > 1600 | Exceptional proposal, dominant in debates |
The ELO system is borrowed directly from the unit distance research project (unit-distance-problem), where hypothesis evaluation used the same adversarial calibration approach. In the governance context, it provides a quantitative signal for the Chancela decision -- proposals with higher ELO ratings have demonstrated their quality through adversarial testing.
Database Models
Three SQLAlchemy models support the governance system:
GovernanceProposal
class GovernanceProposal(TimestampMixin, Base):
__tablename__ = "governance_proposals"
id = Column(String(50), primary_key)
category = Column(String(50), nullable=False)
name = Column(String(200), nullable=False)
content = Column(Text, nullable=False)
rationale = Column(Text, nullable=False)
proposed_by = Column(String(100), nullable=False)
origin = Column(String(50), nullable=False)
status = Column(String(50), default="draft")
elo_rating = Column(Integer, default=1200)
debate_log = Column(JSON, default=list)
failure_context = Column(Text, default="")
current_artifact= Column(Text, default="")
congress_votes = Column(JSON, default=dict)
strategy_notes = Column(Text, default="")
submitted_at = Column(DateTime, nullable=True)
approved_at = Column(DateTime, nullable=True)
approved_by = Column(String(100), nullable=True)
promoted_at = Column(DateTime, nullable=True)
CongressSession
class CongressSession(TimestampMixin, Base):
__tablename__ = "congress_sessions"
id = Column(String(50), primary_key)
convened_at = Column(DateTime, default=utcnow_naive)
proposals_discussed = Column(JSON, default=list)
agents_present = Column(JSON, default=list)
resolutions = Column(JSON, default=list)
closed_at = Column(DateTime, nullable=True)
status = Column(String(50), default="in_session")
QuinquennialPlan
class QuinquennialPlan(TimestampMixin, Base):
__tablename__ = "quinquennial_plans"
id = Column(String(50), primary_key)
title = Column(String(200), nullable=False)
objectives = Column(JSON, default=list)
kpis = Column(JSON, default=dict)
duration_days = Column(Integer, nullable=True)
duration_rationale= Column(Text, default="")
phases = Column(JSON, default=list)
status = Column(String(50), default="proposed")
proposed_by = Column(String(100), default="")
approved_by = Column(String(100), nullable=True)
started_at = Column(DateTime, nullable=True)
completed_at = Column(DateTime, nullable=True)
The QuinquennialPlan represents long-term strategic planning -- titled after the "Five Year Plans" of governance, adapted for the AI workspace context.
API Endpoints
All endpoints are mounted under /api/governance and require authentication.
| Method | Endpoint | Purpose |
|---|---|---|
GET | /api/governance/proposals | List all proposals (optional ?status= filter) |
POST | /api/governance/proposals | Create a new proposal |
GET | /api/governance/proposals/{id} | Get proposal details + debate log |
POST | /api/governance/proposals/{id}/status | Update proposal status |
POST | /api/governance/proposals/{id}/chancela | Human approval/veto |
POST | /api/governance/proposals/{id}/debate | Record a debate round |
POST | /api/governance/congress/convene | Convene a congress session |
POST | /api/governance/congress/{id}/close | Close congress with resolutions |
GET | /api/governance/plans/active | Get the active strategic plan |
POST | /api/governance/plans | Propose a new strategic plan |
Frontend: The Kanban UI
The kanban board is rendered in static/js/governance.js as a drag-and-drop interface:
Column Rendering
Each of the 7 columns is rendered as a vertical strip with:
- A header showing the column title and card count
- A dropzone area accepting draggable proposal cards
- Visual emphasis on the Chancela column (red glow border)
Proposal Cards
Each card displays:
- Proposal name (bold)
- Category badge
- ELO rating
- Proposed by (user/agent name)
- Origin indicator
- Status-specific styling
Cards are draggable (draggable=true) and support standard HTML5 drag-and-drop between columns. When a card is dropped in a new column, updateProposalStatus() calls the API to persist the status change.
Interaction Flow
- User clicks the "Governance" sidebar button
- Chat and other views are hidden; governance view is displayed
fetchProposals()loads all proposals from/api/governance/proposalsrenderCards()distributes proposals into their respective columns- User can drag cards between columns to update status
- User can click a card to view details, debate log, and congress votes
Styling
The kanban board uses the dashboard's CSS variable system:
| Variable | Purpose |
|---|---|
--panel | Column background (#1e2227) |
--border | Column/card borders (#3e4451) |
--bg | Card background (#282c34) |
--red | Chancela column highlight (#e06c75) |
The Chancela column has special visual treatment: a red-tinted border and a box-shadow: 0 0 15px rgba(224, 108, 117, 0.2) glow, signaling that proposals in this column require urgent human attention.
Agent Interaction
Agents interact with the governance system through the tool system. The do_manage_tasks function in tool_implementations.py can:
- Create proposals when the agent identifies a needed change
- Record debate rounds as the agent defends or challenges proposals
- Query proposal status to inform decision-making
Agents cannot invoke the Chancela (human-only), but they can:
- Submit proposals for human review
- Participate in congress debates
- Propose strategic plans through the
CentralCommittee
Cross-References
- co-fita-odysseus -- The parent dashboard hosting the governance system
- co-fita-mcp-servers -- MCP servers whose configurations are governed
- co-fita-harness -- The parent harness with full context
- fitalabs-infra -- Infrastructure and deployment
Implementation Files
| File | Lines | Purpose |
|---|---|---|
src/governance_engine.py | ~209 | Core engine: GovernanceEngine + CentralCommittee |
routes/governance_routes.py | ~137 | FastAPI route layer |
core/database.py | (lines 2357-2407) | 3 SQLAlchemy model definitions |
static/js/governance.js | ~120+ | Kanban frontend (drag-and-drop) |
Design Notes
Human authority is absolute: The Chancela step cannot be bypassed by agents or API calls. Even if a proposal achieves the highest ELO rating and passes congress unanimously, the human principal must explicitly approve it. This is a hard safety boundary.
Debate is quantitative, not just qualitative: The ELO system provides a numerical signal that accumulates across multiple debate rounds. A proposal with ELO 1500 has demonstrated superiority over many opponents, while a proposal at 1000 has consistently lost. This removes purely subjective judgment from the intermediate stages.
The system is recursive: Proposals can modify the governance system itself. A proposal to change the ELO K-factor, add new categories, or modify the congress voting rules would flow through the same pipeline. The Chancela gate ensures the human approves any meta-level changes.
Congress is multi-agent: The agents_present field in CongressSession records which agents participated. This enables analysis of voting patterns and agent alignment over time.
"Protocols are dialectical instruments -- they exist to be challenged and refined."