refactor: Rename SmartTools to CmdForge throughout codebase
- Rename smarttools/ directory to cmdforge/ - Update all Python imports and references - Update documentation (CLAUDE.md, README.md, docs/*.md) - Update Docker and build configs - Update discussion files - Improve dictation error handling in GUI 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
a39253c893
commit
55aec4c7f2
12
AGENTS.md
12
AGENTS.md
|
|
@ -3,31 +3,31 @@
|
|||
## Project Structure & Module Organization
|
||||
- Core library and CLI live in `src/discussions` (CLI entrypoint `cli.py`, models/orchestration in `discussion.py` and `runner.py`, parsing/voting utilities in `markers.py` and `voting.py`, participant registry in `participant.py`).
|
||||
- Tests sit in `tests/` with pytest; mirror module names when adding coverage (e.g., `test_voting.py`).
|
||||
- User-facing docs are under `docs/` (design + implementation notes), with runnable discussion examples in `examples/` and SmartTool configs in `smarttools/`.
|
||||
- User-facing docs are under `docs/` (design + implementation notes), with runnable discussion examples in `examples/` and CmdForge tool configs in `cmdforge/`.
|
||||
- Discussion templates for new files live in `templates/` (`feature.yaml`, `brainstorm.yaml`).
|
||||
|
||||
## Build, Test, and Development Commands
|
||||
- Install in editable mode with dev extras: `python -m pip install -e .[dev]`.
|
||||
- Run the CLI locally: `discussions --help`, `discussions new "My Feature" --template feature`, `discussions turn examples/feature_discussion.md`.
|
||||
- Execute the manual orchestration walkthrough: `bash scripts/run-turn.sh examples/feature_discussion.md` (shows each SmartTool step).
|
||||
- Execute the manual orchestration walkthrough: `bash scripts/run-turn.sh examples/feature_discussion.md` (shows each CmdForge tool step).
|
||||
- Run tests: `pytest` or `pytest --maxfail=1 -q` for quick feedback.
|
||||
|
||||
## Coding Style & Naming Conventions
|
||||
- Follow PEP 8 with 4-space indentation and type hints for public functions; prefer concise module-level docstrings like the existing files.
|
||||
- Keep modules thin: orchestration in Python, heavy lifting in SmartTools via stdin/stdout (see `docs/DESIGN.md` for the Unix-style adapter pattern).
|
||||
- Keep modules thin: orchestration in Python, heavy lifting in CmdForge tools via stdin/stdout (see `docs/DESIGN.md` for the Unix-style adapter pattern).
|
||||
- Use snake_case for modules/functions, CapWords for classes, and uppercase for constants. Avoid adding new global state; prefer pure functions or dataclasses.
|
||||
- New CLI flags should use argparse patterns already present in `cli.py`; align option names with existing verbs (`new`, `turn`, `status`, `comment`, `participants`).
|
||||
|
||||
## Testing Guidelines
|
||||
- Add pytest coverage alongside new code; name tests after the module (`test_<module>.py`) and include scenario-focused test names (`test_consensus_requires_human`).
|
||||
- When touching parsing or voting logic, assert both positive and negative cases (see `tests/test_markers.py` and `tests/test_voting.py`).
|
||||
- If a feature depends on SmartTools output, stub with deterministic JSON fixtures instead of live calls.
|
||||
- If a feature depends on CmdForge tool output, stub with deterministic JSON fixtures instead of live calls.
|
||||
|
||||
## Commit & Pull Request Guidelines
|
||||
- Use short, imperative commit subjects (e.g., `Add CHANGES threshold guard`); keep body lines wrapped and include rationale when non-obvious.
|
||||
- PRs should link related issues, describe behavior changes, and show before/after snippets for CLI flows or discussion markdown changes.
|
||||
- Always note test coverage (`pytest` command) and any SmartTools/config prerequisites for reviewers.
|
||||
- Always note test coverage (`pytest` command) and any CmdForge tool/config prerequisites for reviewers.
|
||||
|
||||
## Security & Configuration Tips
|
||||
- Do not commit API keys or SmartTools cache; local participant configs live in `~/.smarttools/`.
|
||||
- Do not commit API keys or CmdForge cache; local participant configs live in `~/.cmdforge/`.
|
||||
- Favor configuration via environment variables or `.env` ignored files; validate inputs before invoking external tools to avoid malformed prompts.
|
||||
|
|
|
|||
72
CLAUDE.md
72
CLAUDE.md
|
|
@ -20,7 +20,7 @@ pytest tests/test_markers.py::TestExtractVote::test_ready_vote
|
|||
# Run with coverage
|
||||
pytest --cov=discussions
|
||||
|
||||
# Test SmartTools directly (Unix philosophy - test tools independently)
|
||||
# Test CmdForge tools directly (Unix philosophy - test tools independently)
|
||||
cat examples/brainstorm_notification_system.md | discussion-parser | jq .
|
||||
cat examples/brainstorm_notification_system.md | discussion-parser | discussion-vote-counter
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ Orchestrated Discussions is a multi-agent AI discussion orchestrator that manage
|
|||
### Project Ecosystem
|
||||
|
||||
This is the middle layer of a three-project stack:
|
||||
1. **SmartTools** - AI provider abstraction and tool execution (dependency)
|
||||
1. **CmdForge** - AI provider abstraction and tool execution (dependency)
|
||||
2. **Orchestrated Discussions** (this) - Conversation orchestration
|
||||
3. **CascadingDev** - Git-driven automation (depends on this)
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ This is the middle layer of a three-project stack:
|
|||
|
||||
### Core Principles
|
||||
|
||||
1. **Each tool does one thing well** - SmartTools are self-contained, complete units
|
||||
1. **Each tool does one thing well** - CmdForge tools are self-contained, complete units
|
||||
2. **Tools communicate via stdin/stdout** - JSON flows through pipes
|
||||
3. **Tools are composable** - Any tool's output can be another's input
|
||||
4. **No tool knows about another's internals** - Only the interface (stdin/stdout/args)
|
||||
|
|
@ -59,28 +59,28 @@ This is the middle layer of a three-project stack:
|
|||
### Architecture Rules
|
||||
|
||||
**NEVER:**
|
||||
- Import SmartTools internals (`from smarttools.providers import ...`)
|
||||
- Duplicate logic that exists in a SmartTool
|
||||
- Build "helper functions" when you should make a SmartTool
|
||||
- Call AI providers directly - that's what SmartTools are for
|
||||
- Import CmdForge internals (`from cmdforge.providers import ...`)
|
||||
- Duplicate logic that exists in a CmdForge tool
|
||||
- Build "helper functions" when you should make a CmdForge tool
|
||||
- Call AI providers directly - that's what CmdForge tools are for
|
||||
- Put orchestration logic inside a tool (tools are stateless)
|
||||
|
||||
**ALWAYS:**
|
||||
- Call SmartTools via subprocess: `subprocess.run(["tool-name"], input=data, ...)`
|
||||
- Call CmdForge tools via subprocess: `subprocess.run(["tool-name"], input=data, ...)`
|
||||
- Pass data through stdin, receive through stdout
|
||||
- Keep Python layer thin - it only orchestrates, never implements
|
||||
- Each SmartTool must be independently testable: `cat file | tool | jq .`
|
||||
- Create a new SmartTool rather than adding complexity to existing code
|
||||
- Each CmdForge tool must be independently testable: `cat file | tool | jq .`
|
||||
- Create a new CmdForge tool rather than adding complexity to existing code
|
||||
|
||||
### Anti-Pattern Examples
|
||||
|
||||
```python
|
||||
# WRONG - Importing SmartTools internals, bypassing the tool
|
||||
from smarttools.providers import call_provider
|
||||
prompt = build_prompt_in_python(discussion) # Logic that belongs in SmartTool
|
||||
# WRONG - Importing CmdForge internals, bypassing the tool
|
||||
from cmdforge.providers import call_provider
|
||||
prompt = build_prompt_in_python(discussion) # Logic that belongs in CmdForge tool
|
||||
result = call_provider("claude", prompt)
|
||||
|
||||
# RIGHT - Calling the SmartTool via subprocess
|
||||
# RIGHT - Calling the CmdForge tool via subprocess
|
||||
result = subprocess.run(
|
||||
["discussion-architect", "--callout", callout],
|
||||
input=discussion_content,
|
||||
|
|
@ -96,7 +96,7 @@ def count_votes(discussion):
|
|||
ready = sum(1 for v in votes if v == "READY")
|
||||
# ... reimplementing what discussion-vote-counter does
|
||||
|
||||
# RIGHT - Using the SmartTool
|
||||
# RIGHT - Using the CmdForge tool
|
||||
result = subprocess.run(
|
||||
["discussion-vote-counter"],
|
||||
input=parser_output,
|
||||
|
|
@ -126,30 +126,30 @@ The Python code in this project (`runner.py`, `cli.py`, `ui/`) is **orchestratio
|
|||
- Provide user interface
|
||||
|
||||
It should **never** contain:
|
||||
- AI prompt construction (that's in SmartTool configs)
|
||||
- AI prompt construction (that's in CmdForge tool configs)
|
||||
- Vote counting logic (that's `discussion-vote-counter`)
|
||||
- Response parsing logic (that's in each SmartTool's code steps)
|
||||
- Response parsing logic (that's in each CmdForge tool's code steps)
|
||||
- Discussion format knowledge (that's `discussion-parser`)
|
||||
|
||||
---
|
||||
|
||||
### Key Design Decision: Participants ARE SmartTools
|
||||
### Key Design Decision: Participants ARE CmdForge Tools
|
||||
|
||||
Participants are implemented as SmartTools, not a separate system. Each participant lives in `~/.smarttools/discussion-{alias}/config.yaml` and can be:
|
||||
Participants are implemented as CmdForge tools, not a separate system. Each participant lives in `~/.cmdforge/discussion-{alias}/config.yaml` and can be:
|
||||
- Invoked directly for testing: `cat discussion.md | discussion-architect --callout "..."`
|
||||
- Edited via SmartTools TUI for prompt debugging
|
||||
- Created via `discussions participants add` wizard (generates SmartTool config)
|
||||
- Edited via CmdForge TUI for prompt debugging
|
||||
- Created via `discussions participants add` wizard (generates CmdForge tool config)
|
||||
|
||||
This means:
|
||||
- No duplicate participant definition system
|
||||
- Full SmartTools features available (multi-step pipelines, code steps, provider fallbacks)
|
||||
- Full CmdForge features available (multi-step pipelines, code steps, provider fallbacks)
|
||||
- Independent testing and debugging of each participant
|
||||
|
||||
### Core Abstractions
|
||||
|
||||
- **Discussion** (`discussion.py`): A markdown file with metadata headers, context, and comment blocks. Append-only - content grows but never shrinks. State stored in HTML comments (`<!-- Key: value -->`).
|
||||
|
||||
- **Participant**: A SmartTool in `~/.smarttools/discussion-{alias}/`. Discovered by naming convention. Has personality prompt, expertise metadata, and vote behavior. Two types: `voting` and `background`.
|
||||
- **Participant**: A CmdForge tool in `~/.cmdforge/discussion-{alias}/`. Discovered by naming convention. Has personality prompt, expertise metadata, and vote behavior. Two types: `voting` and `background`.
|
||||
|
||||
- **Markers** (`markers.py`): Structured annotations parsed from comment text:
|
||||
- `VOTE: READY|CHANGES|REJECT`
|
||||
|
|
@ -162,7 +162,7 @@ This means:
|
|||
|
||||
- **Voting** (`voting.py`): Consensus calculation with configurable thresholds.
|
||||
|
||||
- **Runner** (`runner.py`): Invokes participant SmartTools via subprocess, parses JSON responses, appends to discussion file.
|
||||
- **Runner** (`runner.py`): Invokes participant CmdForge tools via subprocess, parses JSON responses, appends to discussion file.
|
||||
|
||||
### Discussion File Format
|
||||
|
||||
|
|
@ -209,7 +209,7 @@ phases:
|
|||
|
||||
**How it works:**
|
||||
1. Discussion references template via `<!-- Template: feature -->`
|
||||
2. Participant SmartTools read the template file to get phase context
|
||||
2. Participant CmdForge tools read the template file to get phase context
|
||||
3. AI prompts include phase goal and instructions for context-aware responses
|
||||
|
||||
Participants use `--templates-dir` argument (default: `templates`) to locate template files.
|
||||
|
|
@ -221,13 +221,13 @@ Participants use `--templates-dir` argument (default: `templates`) to locate tem
|
|||
- `VotingConfig.human_required` (default True): Needs human READY vote
|
||||
- Human participants detected by name NOT starting with `ai_`, `ai-`, `bot_`, `bot-`
|
||||
|
||||
### SmartTools Integration
|
||||
### CmdForge Integration
|
||||
|
||||
```
|
||||
Orchestrated Discussions (thin orchestration layer)
|
||||
│ invokes via subprocess
|
||||
▼
|
||||
SmartTools (discussion-* tools)
|
||||
CmdForge (discussion-* tools)
|
||||
│
|
||||
├── Utility tools (code-only):
|
||||
│ - discussion-parser → JSON structured data
|
||||
|
|
@ -250,10 +250,10 @@ SmartTools (discussion-* tools)
|
|||
AI Providers (claude, codex, gemini, etc.)
|
||||
```
|
||||
|
||||
**Everything is a SmartTool** - parsing, validation, orchestration, summarization, and participants. This means:
|
||||
**Everything is a CmdForge tool** - parsing, validation, orchestration, summarization, and participants. This means:
|
||||
- All components testable independently: `cat discussion.md | discussion-parser | jq .`
|
||||
- Full pipelines runnable manually: `cat d.md | discussion-parser | discussion-vote-counter | jq .`
|
||||
- Debuggable via SmartTools TUI
|
||||
- Debuggable via CmdForge TUI
|
||||
- Composable: tools can call other tools
|
||||
|
||||
### Manual Turn Execution
|
||||
|
|
@ -271,9 +271,9 @@ See `scripts/run-turn.sh` for a complete example.
|
|||
|
||||
### Project Files
|
||||
|
||||
- `docs/DESIGN.md` - Full architecture and SmartTool specifications
|
||||
- `docs/DESIGN.md` - Full architecture and CmdForge tool specifications
|
||||
- `docs/IMPLEMENTATION.md` - Phased implementation plan
|
||||
- `smarttools/` - Bundled SmartTool configs (copied to ~/.smarttools/ on install)
|
||||
- `cmdforge/` - Bundled CmdForge tool configs (copied to ~/.cmdforge/ on install)
|
||||
- `templates/` - Discussion workflow templates (phase definitions)
|
||||
- `examples/` - Example discussion files for testing
|
||||
- `scripts/run-turn.sh` - Manual turn orchestration script
|
||||
|
|
@ -288,7 +288,7 @@ Two UI implementations available:
|
|||
- **TUI**: urwid-based, text-only terminal interface, read-aloud buttons
|
||||
|
||||
Both UIs include:
|
||||
- "Read" button on each comment for text-to-speech (requires `~/.smarttools/read-aloud/`)
|
||||
- "Read" button on each comment for text-to-speech (requires `~/.cmdforge/read-aloud/`)
|
||||
- "Artifact" button in comment dialog for creating diagrams/visuals
|
||||
|
||||
### Artifact Editor Integration
|
||||
|
|
@ -350,9 +350,9 @@ python -m src.discussions.ui --tui # TUI
|
|||
| `Enter` | Select |
|
||||
| `Esc` | Close dialogs |
|
||||
|
||||
### SmartTools Arguments
|
||||
### CmdForge Tool Arguments
|
||||
|
||||
Participant SmartTools accept these arguments:
|
||||
Participant CmdForge tools accept these arguments:
|
||||
- `--callout` - Specific question or @mention context
|
||||
- `--templates-dir` - Path to templates directory (default: `templates`)
|
||||
- `--diagrams-dir` - Path to save diagrams (default: `diagrams`)
|
||||
|
|
@ -364,10 +364,10 @@ Participant SmartTools accept these arguments:
|
|||
src/discussions/
|
||||
├── cli.py # CLI entry point (discussions command)
|
||||
├── discussion.py # Discussion model, file I/O
|
||||
├── participant.py # Participant discovery from ~/.smarttools/discussion-*
|
||||
├── participant.py # Participant discovery from ~/.cmdforge/discussion-*
|
||||
├── markers.py # Marker parsing (VOTE:, Q:, TODO:, CONCERN:, etc.)
|
||||
├── voting.py # Consensus calculation
|
||||
├── runner.py # Turn orchestration (calls SmartTools via subprocess)
|
||||
├── runner.py # Turn orchestration (calls CmdForge tools via subprocess)
|
||||
└── ui/
|
||||
├── __init__.py
|
||||
├── __main__.py # Module entry point
|
||||
|
|
|
|||
46
Dockerfile
46
Dockerfile
|
|
@ -1,27 +1,27 @@
|
|||
# Orchestrated Discussions - Multi-agent AI discussion orchestration
|
||||
#
|
||||
# Multi-stage build:
|
||||
# Stage 1: Build SmartTools base
|
||||
# Stage 2: Build Orchestrated Discussions with SmartTools
|
||||
# Stage 1: Build CmdForge base
|
||||
# Stage 2: Build Orchestrated Discussions with CmdForge
|
||||
#
|
||||
# Build: docker build -t orchestrated-discussions .
|
||||
# Run: docker run -it --rm orchestrated-discussions discussions --help
|
||||
# Test: docker run -it --rm orchestrated-discussions pytest -v
|
||||
|
||||
# ==============================================================================
|
||||
# Stage 1: SmartTools Base
|
||||
# Stage 1: CmdForge Base
|
||||
# ==============================================================================
|
||||
FROM python:3.12-slim AS smarttools
|
||||
FROM python:3.12-slim AS cmdforge
|
||||
|
||||
WORKDIR /smarttools
|
||||
WORKDIR /cmdforge
|
||||
|
||||
# Clone SmartTools from Gitea (or provide build arg for local path)
|
||||
ARG SMARTTOOLS_REPO=https://gitea.brrd.tech/rob/SmartTools.git
|
||||
# Clone CmdForge from Gitea (or provide build arg for local path)
|
||||
ARG CMDFORGE_REPO=https://gitea.brrd.tech/rob/CmdForge.git
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends git && \
|
||||
git clone ${SMARTTOOLS_REPO} . || \
|
||||
git clone ${CMDFORGE_REPO} . || \
|
||||
echo "Clone failed - will need COPY in next stage"
|
||||
|
||||
# Install SmartTools
|
||||
# Install CmdForge
|
||||
RUN pip install --no-cache-dir -e . || true
|
||||
|
||||
# ==============================================================================
|
||||
|
|
@ -54,16 +54,16 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy SmartTools from stage 1
|
||||
COPY --from=smarttools /smarttools /smarttools
|
||||
# Copy CmdForge from stage 1
|
||||
COPY --from=cmdforge /cmdforge /cmdforge
|
||||
|
||||
# Install SmartTools
|
||||
RUN pip install --no-cache-dir -e /smarttools
|
||||
# Install CmdForge
|
||||
RUN pip install --no-cache-dir -e /cmdforge
|
||||
|
||||
# Copy Orchestrated Discussions files
|
||||
COPY pyproject.toml README.md ./
|
||||
COPY src/ ./src/
|
||||
COPY smarttools/ ./smarttools/
|
||||
COPY cmdforge/ ./cmdforge/
|
||||
COPY templates/ ./templates/
|
||||
COPY examples/ ./examples/
|
||||
COPY tests/ ./tests/
|
||||
|
|
@ -75,21 +75,21 @@ RUN pip install --no-cache-dir -e ".[dev]"
|
|||
RUN pip install --no-cache-dir dearpygui || echo "dearpygui install failed, GUI will use TUI fallback"
|
||||
|
||||
# Create directories
|
||||
RUN mkdir -p /root/.smarttools /root/.local/bin
|
||||
RUN mkdir -p /root/.cmdforge /root/.local/bin
|
||||
|
||||
# Install bundled discussion SmartTools
|
||||
RUN for tool in smarttools/*/; do \
|
||||
# Install bundled discussion CmdForge tools
|
||||
RUN for tool in cmdforge/*/; do \
|
||||
if [ -d "$tool" ]; then \
|
||||
name=$(basename "$tool"); \
|
||||
cp -r "$tool" /root/.smarttools/; \
|
||||
printf '#!/bin/bash\nexec python3 -m smarttools.runner %s "$@"\n' "$name" > "/root/.local/bin/$name"; \
|
||||
cp -r "$tool" /root/.cmdforge/; \
|
||||
printf '#!/bin/bash\nexec python3 -m cmdforge.runner %s "$@"\n' "$name" > "/root/.local/bin/$name"; \
|
||||
chmod +x "/root/.local/bin/$name"; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
# Install SmartTools example tools and refresh wrappers
|
||||
RUN python /smarttools/examples/install.py 2>/dev/null || true && \
|
||||
smarttools refresh 2>/dev/null || true
|
||||
# Install CmdForge example tools and refresh wrappers
|
||||
RUN python /cmdforge/examples/install.py 2>/dev/null || true && \
|
||||
cmdforge refresh 2>/dev/null || true
|
||||
|
||||
# Add local bin to PATH
|
||||
ENV PATH="/root/.local/bin:${PATH}"
|
||||
|
|
@ -97,7 +97,7 @@ ENV PATH="/root/.local/bin:${PATH}"
|
|||
# Healthcheck - verify key commands work
|
||||
RUN discussions --help && \
|
||||
discussion-parser --help && \
|
||||
smarttools list | head -5
|
||||
cmdforge list | head -5
|
||||
|
||||
# Default: run tests
|
||||
CMD ["pytest", "-v", "tests/"]
|
||||
|
|
|
|||
38
README.md
38
README.md
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
**Multi-agent AI discussion orchestration with voting and phases.**
|
||||
|
||||
Conduct structured discussions between multiple AI personas, each with distinct perspectives, expertise, and voting behavior. Built on the Unix philosophy - each component is a composable SmartTool that can be tested and debugged independently.
|
||||
Conduct structured discussions between multiple AI personas, each with distinct perspectives, expertise, and voting behavior. Built on the Unix philosophy - each component is a composable CmdForge tool that can be tested and debugged independently.
|
||||
|
||||
## Key Features
|
||||
|
||||
|
|
@ -11,7 +11,7 @@ Conduct structured discussions between multiple AI personas, each with distinct
|
|||
- **Phase-based Workflows**: Templates define discussion phases with different goals
|
||||
- **Voting & Consensus**: READY/CHANGES/REJECT votes with configurable thresholds
|
||||
- **Dual UI**: Both graphical (Dear PyGui) and terminal (urwid) interfaces
|
||||
- **Unix Philosophy**: All logic lives in SmartTools, Python layer is thin orchestration
|
||||
- **Unix Philosophy**: All logic lives in CmdForge tools, Python layer is thin orchestration
|
||||
|
||||
## Quick Start
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ discussions ui --tui
|
|||
## Installation
|
||||
|
||||
```bash
|
||||
# Clone and install (SmartTools installed automatically from git)
|
||||
# Clone and install (CmdForge installed automatically from git)
|
||||
git clone https://gitea.brrd.tech/rob/orchestrated-discussions.git
|
||||
cd orchestrated-discussions
|
||||
pip install -e ".[dev]"
|
||||
|
|
@ -54,12 +54,12 @@ pip install -e ".[gui]"
|
|||
|
||||
```bash
|
||||
# Clone all projects
|
||||
git clone https://gitea.brrd.tech/rob/SmartTools.git ~/PycharmProjects/SmartTools
|
||||
git clone https://gitea.brrd.tech/rob/CmdForge.git ~/PycharmProjects/CmdForge
|
||||
git clone https://gitea.brrd.tech/rob/artifact-editor.git ~/PycharmProjects/artifact-editor
|
||||
git clone https://gitea.brrd.tech/rob/orchestrated-discussions.git ~/PycharmProjects/orchestrated-discussions
|
||||
|
||||
# Install in order (editable mode)
|
||||
pip install -e ~/PycharmProjects/SmartTools
|
||||
pip install -e ~/PycharmProjects/CmdForge
|
||||
pip install -e ~/PycharmProjects/artifact-editor
|
||||
pip install -e "~/PycharmProjects/orchestrated-discussions[dev]"
|
||||
```
|
||||
|
|
@ -79,7 +79,7 @@ Run without installing anything locally (dependencies fetched automatically):
|
|||
git clone https://gitea.brrd.tech/rob/orchestrated-discussions.git
|
||||
cd orchestrated-discussions
|
||||
|
||||
# Build (automatically clones SmartTools from Gitea)
|
||||
# Build (automatically clones CmdForge from Gitea)
|
||||
docker-compose build
|
||||
|
||||
# Run tests
|
||||
|
|
@ -96,13 +96,13 @@ docker-compose run --rm shell
|
|||
### Requirements
|
||||
|
||||
- Python 3.10+
|
||||
- [SmartTools](https://gitea.brrd.tech/rob/SmartTools) (installed automatically)
|
||||
- At least one AI provider configured in SmartTools (Claude, Codex, Gemini, etc.)
|
||||
- [CmdForge](https://gitea.brrd.tech/rob/CmdForge) (installed automatically)
|
||||
- At least one AI provider configured in CmdForge (Claude, Codex, Gemini, etc.)
|
||||
|
||||
## How It Works
|
||||
|
||||
1. **Discussions** are markdown files with structured comments and metadata
|
||||
2. **Participants** are AI personas implemented as SmartTools
|
||||
2. **Participants** are AI personas implemented as CmdForge tools
|
||||
3. **Phases** guide discussion through stages (feedback -> review -> vote)
|
||||
4. **Votes** (READY/CHANGES/REJECT) determine consensus
|
||||
5. **Markers** (Q:, TODO:, DECISION:, CONCERN:) capture structured information
|
||||
|
|
@ -117,12 +117,12 @@ User/CLI/UI
|
|||
│ Orchestrated Discussions │
|
||||
│ - Thin orchestration layer (runner.py) │
|
||||
│ - File I/O, turn sequencing │
|
||||
│ - Calls SmartTools via subprocess │
|
||||
│ - Calls CmdForge tools via subprocess │
|
||||
└────────────────────┬─────────────────────┘
|
||||
│ stdin/stdout
|
||||
▼
|
||||
┌──────────────────────────────────────────┐
|
||||
│ SmartTools (discussion-*) │
|
||||
│ CmdForge (discussion-*) │
|
||||
│ │
|
||||
│ Utility: parser, validator │
|
||||
│ Orchestration: vote-counter, router │
|
||||
|
|
@ -141,7 +141,7 @@ User/CLI/UI
|
|||
| `discussions status <file>` | Show discussion status, votes, and consensus |
|
||||
| `discussions turn <file> [@participants]` | Run a discussion turn |
|
||||
| `discussions comment <file> <text>` | Add a human comment |
|
||||
| `discussions participants` | List available participant SmartTools |
|
||||
| `discussions participants` | List available participant CmdForge tools |
|
||||
| `discussions advance <file> --phase <id>` | Advance to a specific phase |
|
||||
| `discussions cleanup [directory]` | Find orphaned diagrams not referenced by any discussion |
|
||||
| `discussions ui [directory]` | Launch interactive UI |
|
||||
|
|
@ -197,7 +197,7 @@ Templates define the workflow phases for different discussion types.
|
|||
| `reality_check` | Ground in reality | No |
|
||||
| `decide` | Commit to approach | Yes (67% READY) |
|
||||
|
||||
## Bundled SmartTools
|
||||
## Bundled CmdForge Tools
|
||||
|
||||
### Utility Tools (code-only)
|
||||
|
||||
|
|
@ -328,7 +328,7 @@ python -m src.discussions.ui --tui
|
|||
| `Enter` | Select |
|
||||
| `Esc` | Close dialogs |
|
||||
|
||||
## Testing SmartTools Directly
|
||||
## Testing CmdForge Tools Directly
|
||||
|
||||
The Unix philosophy means you can test each tool independently:
|
||||
|
||||
|
|
@ -354,14 +354,14 @@ orchestrated-discussions/
|
|||
│ ├── cli.py # CLI entry point
|
||||
│ ├── discussion.py # Discussion model, file I/O
|
||||
│ ├── markers.py # Marker parsing (VOTE, Q, TODO, etc.)
|
||||
│ ├── participant.py # Participant discovery from ~/.smarttools/
|
||||
│ ├── runner.py # Turn orchestration (calls SmartTools)
|
||||
│ ├── participant.py # Participant discovery from ~/.cmdforge/
|
||||
│ ├── runner.py # Turn orchestration (calls CmdForge tools)
|
||||
│ ├── voting.py # Consensus calculation
|
||||
│ └── ui/
|
||||
│ ├── gui.py # Dear PyGui interface
|
||||
│ ├── tui.py # urwid terminal interface
|
||||
│ └── widgets.py # Shared UI components
|
||||
├── smarttools/ # Bundled SmartTool configs
|
||||
├── cmdforge/ # Bundled CmdForge tool configs
|
||||
├── templates/ # Discussion workflow templates
|
||||
├── examples/ # Example discussion files
|
||||
├── scripts/ # Manual orchestration scripts
|
||||
|
|
@ -371,7 +371,7 @@ orchestrated-discussions/
|
|||
|
||||
## Documentation
|
||||
|
||||
- [Design Document](docs/DESIGN.md) - Full architecture and SmartTool specs
|
||||
- [Design Document](docs/DESIGN.md) - Full architecture and CmdForge tool specs
|
||||
- [Implementation Plan](docs/IMPLEMENTATION.md) - Phased development plan
|
||||
- [Pipeline Schema](docs/PIPELINE_SCHEMA.md) - Turn pipeline configuration
|
||||
|
||||
|
|
@ -379,7 +379,7 @@ orchestrated-discussions/
|
|||
|
||||
This is part of a three-project ecosystem:
|
||||
|
||||
1. **SmartTools** - AI provider abstraction and tool execution
|
||||
1. **CmdForge** - AI provider abstraction and tool execution
|
||||
2. **Orchestrated Discussions** (this project) - Multi-agent conversation orchestration
|
||||
3. **CascadingDev** - Git-driven automation (uses both above)
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ Primary integration with **orchestrated-discussions** project:
|
|||
## Questions to Explore
|
||||
|
||||
- What's the right UI framework? (urwid TUI, Dear PyGui, web-based?)
|
||||
- How should AI assistance work? (SmartTools integration?)
|
||||
- How should AI assistance work? (CmdForge integration?)
|
||||
- What's the MVP feature set?
|
||||
- How do we handle 3D model preview?
|
||||
- Should we support collaborative editing?
|
||||
|
|
@ -86,7 +86,7 @@ This is 6+ months of work for a feature that needs to ship in weeks.
|
|||
That's it. No AI, no preview, no 3D. Just a working integration.
|
||||
|
||||
**Defer to v2:**
|
||||
- AI assistance (SmartTools)
|
||||
- AI assistance (CmdForge)
|
||||
- Live preview (nice-to-have, not blocking)
|
||||
- Additional formats (add after first one works)
|
||||
- Voice input (future)
|
||||
|
|
@ -265,18 +265,18 @@ RECOMMENDATION: **Hybrid approach** - TUI for text-based formats (PlantUML, Merm
|
|||
|
||||
ARTIFACT: diagrams/artifact-editor-architecture.puml
|
||||
|
||||
Key principle: **Renderers are stateless SmartTools**
|
||||
Key principle: **Renderers are stateless CmdForge**
|
||||
|
||||
```
|
||||
artifact-editor (orchestration)
|
||||
↓ subprocess
|
||||
artifact-render-{format} (SmartTools)
|
||||
artifact-render-{format} (CmdForge)
|
||||
↓
|
||||
External tools (plantuml.jar, mermaid-cli, openscad)
|
||||
```
|
||||
|
||||
DON'T: Build rendering logic into the editor
|
||||
DO: Each renderer is a SmartTool that can be tested independently:
|
||||
DO: Each renderer is a CmdForge tool that can be tested independently:
|
||||
```bash
|
||||
echo '@startuml\nA -> B\n@enduml' | artifact-render-plantuml > out.svg
|
||||
```
|
||||
|
|
@ -286,9 +286,9 @@ echo '@startuml\nA -> B\n@enduml' | artifact-render-plantuml > out.svg
|
|||
Two architectural patterns emerge:
|
||||
|
||||
**Pattern A: AI as orchestrator** (RECOMMENDED)
|
||||
- User voice → `artifact-assistant` SmartTool → generates code → editor displays
|
||||
- User voice → `artifact-assistant` CmdForge tool → generates code → editor displays
|
||||
- Conversational loop: user refines → tool regenerates
|
||||
- Editor remains thin, AI in separate SmartTool
|
||||
- Editor remains thin, AI in separate CmdForge tool
|
||||
|
||||
**Pattern B: AI embedded in editor**
|
||||
- Tighter coupling, harder to test, breaks Unix philosophy
|
||||
|
|
@ -311,7 +311,7 @@ RECOMMENDATION: **File-based state**
|
|||
- Solution: Render process pool, preview throttling
|
||||
|
||||
2. **Voice Input Dependencies**: Adds heavyweight deps (speech recognition). Could bloat the tool.
|
||||
- Solution: Separate `artifact-voice` SmartTool, optional integration
|
||||
- Solution: Separate `artifact-voice` CmdForge tool, optional integration
|
||||
|
||||
3. **Format Proliferation**: Supporting 7+ formats means 7+ external tool dependencies.
|
||||
- Solution: Plugin architecture, core ships with Mermaid+PlantUML only
|
||||
|
|
@ -321,10 +321,10 @@ RECOMMENDATION: **File-based state**
|
|||
```
|
||||
artifact-editor # Thin orchestrator (urwid TUI)
|
||||
├── Core loop: edit → render → display
|
||||
├── Calls SmartTools via subprocess
|
||||
├── Calls CmdForge via subprocess
|
||||
└── File-based state persistence
|
||||
|
||||
SmartTools ecosystem:
|
||||
CmdForge ecosystem:
|
||||
├── artifact-render-{format} # Stateless renderers
|
||||
├── artifact-assistant # AI code generation
|
||||
├── artifact-voice # Speech → text (optional)
|
||||
|
|
@ -342,7 +342,7 @@ External tools (user-installed):
|
|||
**Phase 1 (MVP)**:
|
||||
- TUI editor (urwid)
|
||||
- Mermaid + PlantUML support (most common in orchestrated-discussions)
|
||||
- Basic `artifact-assistant` SmartTool (text prompt → diagram code)
|
||||
- Basic `artifact-assistant` CmdForge tool (text prompt → diagram code)
|
||||
- File output contract
|
||||
|
||||
**Phase 2**:
|
||||
|
|
@ -373,7 +373,7 @@ VOTE: CHANGES
|
|||
## Required Decisions Before Implementation
|
||||
|
||||
1. ✅ Confirm hybrid TUI + external viewer approach
|
||||
2. ✅ Confirm SmartTools-based renderer architecture
|
||||
2. ✅ Confirm CmdForge-based renderer architecture
|
||||
3. ❓ Define MVP format support (recommend: Mermaid + PlantUML only)
|
||||
4. ❓ Decide on edit-existing vs. create-only
|
||||
5. ❓ Choose modal vs. modeless editing
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
# Orchestrated Discussions - Multi-agent AI discussion orchestration
|
||||
#
|
||||
# Quick Start:
|
||||
# docker-compose build # Build the image (clones SmartTools from Gitea)
|
||||
# docker-compose build # Build the image (clones CmdForge from Gitea)
|
||||
# docker-compose run --rm test # Run tests
|
||||
# docker-compose run --rm cli discussions --help
|
||||
#
|
||||
# Dependencies:
|
||||
# - SmartTools (cloned automatically from Gitea during build)
|
||||
# - CmdForge (cloned automatically from Gitea during build)
|
||||
|
||||
version: '3.8'
|
||||
|
||||
|
|
@ -19,10 +19,10 @@ services:
|
|||
context: .
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
SMARTTOOLS_REPO: https://gitea.brrd.tech/rob/SmartTools.git
|
||||
CMDFORGE_REPO: https://gitea.brrd.tech/rob/CmdForge.git
|
||||
image: orchestrated-discussions:latest
|
||||
volumes:
|
||||
- smarttools-data:/root/.smarttools
|
||||
- cmdforge-data:/root/.cmdforge
|
||||
- ./examples:/app/examples:ro
|
||||
- ./templates:/app/templates:ro
|
||||
command: ["discussions", "--help"]
|
||||
|
|
@ -35,10 +35,10 @@ services:
|
|||
context: .
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
SMARTTOOLS_REPO: https://gitea.brrd.tech/rob/SmartTools.git
|
||||
CMDFORGE_REPO: https://gitea.brrd.tech/rob/CmdForge.git
|
||||
image: orchestrated-discussions:latest
|
||||
volumes:
|
||||
- smarttools-data:/root/.smarttools
|
||||
- cmdforge-data:/root/.cmdforge
|
||||
- ./examples:/app/examples:ro
|
||||
command: >
|
||||
bash -c "
|
||||
|
|
@ -46,8 +46,8 @@ services:
|
|||
echo '=== Orchestrated Discussions Tests ==='
|
||||
echo ''
|
||||
|
||||
echo '1. Checking SmartTools...'
|
||||
smarttools list | head -5
|
||||
echo '1. Checking CmdForge...'
|
||||
cmdforge list | head -5
|
||||
echo ''
|
||||
|
||||
echo '2. Checking discussion tools...'
|
||||
|
|
@ -80,12 +80,12 @@ services:
|
|||
context: .
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
SMARTTOOLS_REPO: https://gitea.brrd.tech/rob/SmartTools.git
|
||||
CMDFORGE_REPO: https://gitea.brrd.tech/rob/CmdForge.git
|
||||
image: orchestrated-discussions:latest
|
||||
environment:
|
||||
- DISPLAY=${DISPLAY:-:0}
|
||||
volumes:
|
||||
- smarttools-data:/root/.smarttools
|
||||
- cmdforge-data:/root/.cmdforge
|
||||
- ./examples:/app/examples
|
||||
- /tmp/.X11-unix:/tmp/.X11-unix:ro
|
||||
command: ["discussions", "ui"]
|
||||
|
|
@ -99,10 +99,10 @@ services:
|
|||
context: .
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
SMARTTOOLS_REPO: https://gitea.brrd.tech/rob/SmartTools.git
|
||||
CMDFORGE_REPO: https://gitea.brrd.tech/rob/CmdForge.git
|
||||
image: orchestrated-discussions:latest
|
||||
volumes:
|
||||
- smarttools-data:/root/.smarttools
|
||||
- cmdforge-data:/root/.cmdforge
|
||||
- ./examples:/app/examples
|
||||
- ./templates:/app/templates
|
||||
command: ["/bin/bash"]
|
||||
|
|
@ -110,14 +110,14 @@ services:
|
|||
tty: true
|
||||
|
||||
volumes:
|
||||
smarttools-data:
|
||||
# Persists ~/.smarttools between container runs
|
||||
cmdforge-data:
|
||||
# Persists ~/.cmdforge between container runs
|
||||
|
||||
# ==============================================================================
|
||||
# Usage Examples
|
||||
# ==============================================================================
|
||||
#
|
||||
# Build (fetches SmartTools from Gitea automatically):
|
||||
# Build (fetches CmdForge from Gitea automatically):
|
||||
# docker-compose build
|
||||
#
|
||||
# Run tests:
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@
|
|||
| CLI | Complete | All commands implemented |
|
||||
| GUI | Complete | Dear PyGui interface |
|
||||
| TUI | Complete | urwid terminal interface |
|
||||
| Utility SmartTools | Complete | parser, validator, summarizer |
|
||||
| Orchestration SmartTools | Complete | vote-counter, mention-router, status-promoter, turn-appender, config |
|
||||
| Participant SmartTools | Complete | architect, security, pragmatist, moderator, diagram-editor |
|
||||
| Utility CmdForge tools | Complete | parser, validator, summarizer |
|
||||
| Orchestration CmdForge tools | Complete | vote-counter, mention-router, status-promoter, turn-appender, config |
|
||||
| Participant CmdForge tools | Complete | architect, security, pragmatist, moderator, diagram-editor |
|
||||
| Templates | Complete | feature.yaml, brainstorm.yaml |
|
||||
|
||||
---
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
**This project strictly follows the Unix Philosophy:**
|
||||
|
||||
1. **Each tool does one thing well** - SmartTools are self-contained, complete units
|
||||
1. **Each tool does one thing well** - CmdForge tools are self-contained, complete units
|
||||
2. **Tools communicate via stdin/stdout** - JSON flows through pipes
|
||||
3. **Tools are composable** - Any tool's output can be another's input
|
||||
4. **The Python layer is thin orchestration only** - It calls tools, never reimplements their logic
|
||||
|
|
@ -37,7 +37,7 @@ See `CLAUDE.md` for detailed architectural rules and anti-patterns.
|
|||
|
||||
This project is part of a three-project ecosystem:
|
||||
|
||||
1. **SmartTools** - Foundation Layer
|
||||
1. **CmdForge** - Foundation Layer
|
||||
- AI provider abstraction, prompt execution pipelines, YAML-defined tools
|
||||
|
||||
2. **Orchestrated Discussions** - Conversation Layer (this project)
|
||||
|
|
@ -51,7 +51,7 @@ This project is part of a three-project ecosystem:
|
|||
### Design Goals
|
||||
|
||||
1. **Workflow independence** - Operates independently of Git/CascadingDev
|
||||
2. **SmartTools as the provider layer** - All AI inference through SmartTools
|
||||
2. **CmdForge as the provider layer** - All AI inference through CmdForge
|
||||
3. **Extensible participants** - Support AI personas and human participants
|
||||
4. **Multiple interfaces** - CLI, Python API, TUI/GUI
|
||||
5. **Append-only discussion files** - Human-readable, Git-friendly
|
||||
|
|
@ -80,7 +80,7 @@ This project is part of a three-project ecosystem:
|
|||
└─────────────────────┬──────────────────────┘
|
||||
│
|
||||
┌─────────────────────▼──────────────────────┐
|
||||
│ SmartTools │
|
||||
│ CmdForge │
|
||||
│ - AI provider abstraction │
|
||||
│ - Inference dispatch + fallback chains │
|
||||
│ - YAML-defined tool pipelines │
|
||||
|
|
@ -96,10 +96,10 @@ orchestrated-discussions/
|
|||
│ ├── __init__.py # Package exports, version
|
||||
│ ├── cli.py # CLI entry point (argparse)
|
||||
│ ├── discussion.py # Discussion model, file I/O
|
||||
│ ├── participant.py # Participant discovery from ~/.smarttools/
|
||||
│ ├── participant.py # Participant discovery from ~/.cmdforge/
|
||||
│ ├── markers.py # Marker parsing (VOTE, Q, TODO, etc.)
|
||||
│ ├── voting.py # Voting + consensus calculation
|
||||
│ ├── runner.py # Turn orchestration (calls SmartTools)
|
||||
│ ├── runner.py # Turn orchestration (calls CmdForge tools)
|
||||
│ └── ui/
|
||||
│ ├── __init__.py # UI module exports
|
||||
│ ├── __main__.py # Module entry point
|
||||
|
|
@ -107,7 +107,7 @@ orchestrated-discussions/
|
|||
│ ├── tui.py # urwid terminal interface
|
||||
│ └── widgets.py # Shared UI components
|
||||
│
|
||||
├── smarttools/ # Bundled SmartTool configs
|
||||
├── cmdforge/ # Bundled CmdForge tool configs
|
||||
│ ├── discussion-parser/
|
||||
│ ├── discussion-validator/
|
||||
│ ├── discussion-summarizer/
|
||||
|
|
@ -200,11 +200,11 @@ VOTE: CHANGES
|
|||
|
||||
### 2. Participant
|
||||
|
||||
Participants are SmartTools with the naming convention `discussion-{alias}`:
|
||||
Participants are CmdForge tools with the naming convention `discussion-{alias}`:
|
||||
|
||||
- **Invoked directly** for testing: `cat discussion.md | discussion-architect --callout "..."`
|
||||
- **Edited via SmartTools TUI** for prompt debugging
|
||||
- **Discovered automatically** by scanning `~/.smarttools/discussion-*`
|
||||
- **Edited via CmdForge TUI** for prompt debugging
|
||||
- **Discovered automatically** by scanning `~/.cmdforge/discussion-*`
|
||||
|
||||
#### Participant Types
|
||||
|
||||
|
|
@ -317,14 +317,14 @@ A Turn is one round of participant responses. The runner:
|
|||
|
||||
1. Loads discussion and parses current state
|
||||
2. Determines who should respond (mentions or all)
|
||||
3. Calls each participant SmartTool in parallel
|
||||
3. Calls each participant CmdForge tool in parallel
|
||||
4. Appends responses to discussion file
|
||||
5. Counts votes and checks consensus
|
||||
6. Promotes status if consensus reached
|
||||
|
||||
---
|
||||
|
||||
## SmartTools Integration
|
||||
## CmdForge Integration
|
||||
|
||||
### Tool Pipeline Architecture
|
||||
|
||||
|
|
@ -333,12 +333,12 @@ A Turn is one round of participant responses. The runner:
|
|||
│ Orchestrated Discussions │
|
||||
│ - Thin orchestration layer (runner.py) │
|
||||
│ - File I/O, turn sequencing │
|
||||
│ - Invokes SmartTools for ALL logic │
|
||||
│ - Invokes CmdForge tools for ALL logic │
|
||||
└─────────────────────┬───────────────────────────────────┘
|
||||
│ invokes SmartTools via subprocess
|
||||
│ invokes CmdForge tools via subprocess
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ SmartTools (discussion-* tools) │
|
||||
│ CmdForge (discussion-* tools) │
|
||||
│ │
|
||||
│ Utility tools: │
|
||||
│ - discussion-parser (extract structured data) │
|
||||
|
|
@ -362,7 +362,7 @@ A Turn is one round of participant responses. The runner:
|
|||
│ uses providers (for AI steps)
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ SmartTools Providers │
|
||||
│ CmdForge Providers │
|
||||
│ claude-sonnet, claude-haiku, opencode-deepseek, etc. │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
|
@ -432,7 +432,7 @@ cat discussion.md | discussion-parser | discussion-mention-router
|
|||
|
||||
---
|
||||
|
||||
## Bundled SmartTools
|
||||
## Bundled CmdForge Tools
|
||||
|
||||
### Utility Tools (Code-only)
|
||||
|
||||
|
|
@ -651,7 +651,7 @@ if result.reached:
|
|||
else:
|
||||
print(f"Blocked: {result.reason}")
|
||||
|
||||
# Run turn via SmartTools pipeline
|
||||
# Run turn via CmdForge pipeline
|
||||
from pathlib import Path
|
||||
result = run_pipeline_turn(
|
||||
discussion_path=Path("feature-x.md"),
|
||||
|
|
@ -720,10 +720,10 @@ output:
|
|||
|
||||
### Participant Discovery
|
||||
|
||||
Participants are discovered by scanning `~/.smarttools/` for tools matching `discussion-*`:
|
||||
Participants are discovered by scanning `~/.cmdforge/` for tools matching `discussion-*`:
|
||||
|
||||
```bash
|
||||
~/.smarttools/
|
||||
~/.cmdforge/
|
||||
├── discussion-architect/config.yaml # @architect
|
||||
├── discussion-security/config.yaml # @security
|
||||
├── discussion-pragmatist/config.yaml # @pragmatist
|
||||
|
|
@ -753,7 +753,7 @@ pytest tests/test_markers.py
|
|||
pytest --cov=discussions
|
||||
```
|
||||
|
||||
### SmartTools Integration Tests
|
||||
### CmdForge Integration Tests
|
||||
|
||||
```bash
|
||||
# Test parser
|
||||
|
|
@ -785,7 +785,7 @@ Visual documentation is available in `docs/diagrams/`:
|
|||
| [turn-execution-sequence.puml](diagrams/turn-execution-sequence.puml) | Sequence diagram showing how a discussion turn flows through the system |
|
||||
| [architecture-component.puml](diagrams/architecture-component.puml) | Component diagram showing the overall system architecture |
|
||||
| [core-class-diagram.puml](diagrams/core-class-diagram.puml) | Class diagram of the Python module structure |
|
||||
| [smarttools-pipeline-flow.puml](diagrams/smarttools-pipeline-flow.puml) | Activity diagram showing data flow through SmartTools pipeline |
|
||||
| [cmdforge-pipeline-flow.puml](diagrams/cmdforge-pipeline-flow.puml) | Activity diagram showing data flow through CmdForge pipeline |
|
||||
| [discussion-state-machine.puml](diagrams/discussion-state-machine.puml) | State machine showing discussion lifecycle and status transitions |
|
||||
|
||||
To render diagrams:
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@ The core functionality is fully implemented and working. The project is usable f
|
|||
|
||||
## Implementation Phases
|
||||
|
||||
### Phase 0: SmartTool Configs - COMPLETE
|
||||
### Phase 0: CmdForge Tool Configs - COMPLETE
|
||||
|
||||
All SmartTool configs have been created and tested.
|
||||
All CmdForge tool configs have been created and tested.
|
||||
|
||||
| Tool | Status | Notes |
|
||||
|------|--------|-------|
|
||||
|
|
@ -42,21 +42,21 @@ cat examples/voted_discussion.md | discussion-parser | discussion-vote-counter
|
|||
|
||||
### Phase 1: Core Library - COMPLETE
|
||||
|
||||
Python library wrapping SmartTools with clean API.
|
||||
Python library wrapping CmdForge tools with clean API.
|
||||
|
||||
| Module | Status | Notes |
|
||||
|--------|--------|-------|
|
||||
| `discussion.py` | Complete | Discussion model, load/save, add_comment |
|
||||
| `markers.py` | Complete | Marker parsing (VOTE, Q, TODO, etc.) |
|
||||
| `voting.py` | Complete | Consensus calculation, VotingConfig |
|
||||
| `participant.py` | Complete | Participant discovery from ~/.smarttools/ |
|
||||
| `participant.py` | Complete | Participant discovery from ~/.cmdforge/ |
|
||||
| `runner.py` | Complete | Pipeline-based turn execution |
|
||||
|
||||
**Key Features:**
|
||||
- `Discussion.load()` / `Discussion.create()` / `Discussion.save()`
|
||||
- `Discussion.add_comment()` with vote support
|
||||
- `Discussion.check_consensus()` with configurable thresholds
|
||||
- `run_pipeline_turn()` for SmartTools-based turn execution
|
||||
- `run_pipeline_turn()` for CmdForge-based turn execution
|
||||
- Participant discovery via `ParticipantRegistry`
|
||||
|
||||
---
|
||||
|
|
@ -69,7 +69,7 @@ All CLI commands implemented and working.
|
|||
|---------|--------|-------|
|
||||
| `discussions new` | Complete | Create new discussion file |
|
||||
| `discussions status` | Complete | Show status, votes, consensus |
|
||||
| `discussions turn` | Complete | Run turn with SmartTools |
|
||||
| `discussions turn` | Complete | Run turn with CmdForge tools |
|
||||
| `discussions comment` | Complete | Add human comment with vote |
|
||||
| `discussions participants` | Complete | List discovered participants |
|
||||
| `discussions advance` | Complete | Advance to specific phase |
|
||||
|
|
@ -160,7 +160,7 @@ orchestrated-discussions/
|
|||
│ ├── tui.py # urwid
|
||||
│ └── widgets.py # Shared components
|
||||
│
|
||||
├── smarttools/ # 14 tool configs
|
||||
├── cmdforge/ # 14 tool configs
|
||||
├── templates/ # 2 templates
|
||||
├── examples/ # 5 example discussions
|
||||
├── scripts/ # run-turn.sh
|
||||
|
|
@ -180,7 +180,7 @@ orchestrated-discussions/
|
|||
- Phase-aware participant behavior
|
||||
- Status promotion on consensus
|
||||
- Human comment addition with votes
|
||||
- Participant discovery from ~/.smarttools/
|
||||
- Participant discovery from ~/.cmdforge/
|
||||
- Both GUI and TUI interfaces
|
||||
- PlantUML diagram viewing
|
||||
|
||||
|
|
@ -227,7 +227,7 @@ pytest tests/test_voting.py -v
|
|||
|
||||
### Run Integration Tests
|
||||
```bash
|
||||
# Test SmartTools directly
|
||||
# Test CmdForge tools directly
|
||||
cat examples/brainstorm_notification_system.md | discussion-parser | jq .
|
||||
|
||||
# Test full pipeline
|
||||
|
|
@ -251,7 +251,7 @@ discussions ui
|
|||
### Required
|
||||
- Python 3.10+
|
||||
- PyYAML >= 6.0
|
||||
- smarttools >= 0.1.0
|
||||
- cmdforge >= 0.1.0
|
||||
|
||||
### Optional
|
||||
- urwid >= 2.1.0 (TUI)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
## Overview
|
||||
|
||||
Each template can define a `turn_pipeline` that specifies which SmartTools to run and how to pipe data between them. The runner is thin orchestration - it just executes tools and pipes data, with no business logic.
|
||||
Each template can define a `turn_pipeline` that specifies which CmdForge tools to run and how to pipe data between them. The runner is thin orchestration - it just executes tools and pipes data, with no business logic.
|
||||
|
||||
## Design Philosophy
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ cat updated.md | discussion-parser | discussion-vote-counter > votes.json
|
|||
```yaml
|
||||
turn_pipeline:
|
||||
steps:
|
||||
- tool: <tool-name> # Required: SmartTool to execute
|
||||
- tool: <tool-name> # Required: CmdForge tool to execute
|
||||
input: <variable> # What to pipe to stdin (default: $discussion)
|
||||
output: <variable> # Where to store stdout (default: discarded)
|
||||
args: # CLI arguments
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
<!-- DISCUSSION -->
|
||||
<!-- Title: general discussion -->
|
||||
<!-- Phase: initial_feedback -->
|
||||
<!-- Status: OPEN -->
|
||||
<!-- Created: 2026-01-04T05:36:51Z -->
|
||||
<!-- Template: brainstorm -->
|
||||
<!-- Participants: architect, backend, designer, ux, frontend -->
|
||||
|
||||
# general discussion
|
||||
|
||||
## Context
|
||||
This i just a general brainstorming discussion.
|
||||
|
||||
---
|
||||
|
||||
*Discussion begins below.*
|
||||
|
|
@ -28,7 +28,7 @@ classifiers = [
|
|||
]
|
||||
dependencies = [
|
||||
"PyYAML>=6.0",
|
||||
"smarttools @ git+https://gitea.brrd.tech/rob/SmartTools.git",
|
||||
"cmdforge @ git+https://gitea.brrd.tech/rob/CmdForge.git",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/bash
|
||||
# run-turn.sh - Manual orchestration of a discussion turn
|
||||
#
|
||||
# This script demonstrates how all the SmartTools chain together.
|
||||
# This script demonstrates how all the CmdForge tools chain together.
|
||||
# It does exactly what `discussions turn feature.md` would do,
|
||||
# but each step is visible and debuggable.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ def cmd_comment(args) -> int:
|
|||
|
||||
|
||||
def cmd_participants(args) -> int:
|
||||
"""List available participants (discovered from ~/.smarttools/)."""
|
||||
"""List available participants (discovered from ~/.cmdforge/)."""
|
||||
from .participant import get_registry
|
||||
|
||||
registry = get_registry()
|
||||
|
|
@ -200,8 +200,8 @@ def cmd_participants(args) -> int:
|
|||
background = registry.get_background()
|
||||
|
||||
if not voting and not background:
|
||||
print("No participants found in ~/.smarttools/")
|
||||
print("Install discussion SmartTools or create participants with:")
|
||||
print("No participants found in ~/.cmdforge/")
|
||||
print("Install discussion CmdForge tools or create participants with:")
|
||||
print(" discussions participants add <alias>")
|
||||
return 0
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
"""
|
||||
Participant discovery for Orchestrated Discussions.
|
||||
|
||||
Participants are SmartTools with the naming convention `discussion-{alias}`.
|
||||
This module discovers them by scanning ~/.smarttools/ directory.
|
||||
Participants are CmdForge tools with the naming convention `discussion-{alias}`.
|
||||
This module discovers them by scanning ~/.cmdforge/ directory.
|
||||
|
||||
See docs/DESIGN.md for participant specification.
|
||||
"""
|
||||
|
|
@ -40,20 +40,20 @@ DEFAULT_COLOR = (150, 150, 150)
|
|||
@dataclass
|
||||
class Participant:
|
||||
"""
|
||||
Metadata about a participant SmartTool.
|
||||
Metadata about a participant CmdForge tool.
|
||||
|
||||
This is discovery metadata only - NOT used to build prompts or call AI.
|
||||
All logic lives in the SmartTool config itself.
|
||||
All logic lives in the CmdForge tool config itself.
|
||||
|
||||
Attributes:
|
||||
alias: Short mention name (e.g., "architect")
|
||||
name: Display name (e.g., "AI-Architect")
|
||||
description: Brief description from SmartTool config
|
||||
description: Brief description from CmdForge tool config
|
||||
participant_type: "voting" or "background"
|
||||
voice: TTS voice for reading comments aloud
|
||||
provider: AI provider to use (e.g., "claude-sonnet", "opencode-deepseek")
|
||||
color: RGB tuple for display (e.g., (100, 150, 255) for blue)
|
||||
tool_path: Path to the SmartTool config directory
|
||||
tool_path: Path to the CmdForge tool config directory
|
||||
"""
|
||||
alias: str
|
||||
name: str
|
||||
|
|
@ -69,13 +69,13 @@ class Participant:
|
|||
return self.participant_type == "voting"
|
||||
|
||||
def tool_name(self) -> str:
|
||||
"""Return the SmartTool name for subprocess calls."""
|
||||
"""Return the CmdForge tool name for subprocess calls."""
|
||||
return f"discussion-{self.alias}"
|
||||
|
||||
|
||||
def _parse_smarttool_config(config_path: Path) -> Optional[Participant]:
|
||||
def _parse_cmdforge_config(config_path: Path) -> Optional[Participant]:
|
||||
"""
|
||||
Parse a SmartTool config.yaml to extract participant metadata.
|
||||
Parse a CmdForge tool config.yaml to extract participant metadata.
|
||||
|
||||
Args:
|
||||
config_path: Path to config.yaml
|
||||
|
|
@ -151,29 +151,29 @@ def _parse_smarttool_config(config_path: Path) -> Optional[Participant]:
|
|||
return None
|
||||
|
||||
|
||||
def discover_participants(smarttools_dir: Path = None) -> list[Participant]:
|
||||
def discover_participants(cmdforge_dir: Path = None) -> list[Participant]:
|
||||
"""
|
||||
Discover participant SmartTools by scanning ~/.smarttools/.
|
||||
Discover participant CmdForge tools by scanning ~/.cmdforge/.
|
||||
|
||||
Participants are SmartTools matching the pattern `discussion-{alias}`
|
||||
Participants are CmdForge tools matching the pattern `discussion-{alias}`
|
||||
that are NOT utility tools (parser, vote-counter, etc.).
|
||||
|
||||
Args:
|
||||
smarttools_dir: Override SmartTools directory (default: ~/.smarttools)
|
||||
cmdforge_dir: Override CmdForge directory (default: ~/.cmdforge)
|
||||
|
||||
Returns:
|
||||
List of discovered Participant objects
|
||||
"""
|
||||
if smarttools_dir is None:
|
||||
smarttools_dir = Path.home() / ".smarttools"
|
||||
if cmdforge_dir is None:
|
||||
cmdforge_dir = Path.home() / ".cmdforge"
|
||||
|
||||
if not smarttools_dir.exists():
|
||||
if not cmdforge_dir.exists():
|
||||
return []
|
||||
|
||||
participants = []
|
||||
|
||||
# Scan for discussion-* directories
|
||||
for tool_dir in smarttools_dir.iterdir():
|
||||
for tool_dir in cmdforge_dir.iterdir():
|
||||
if not tool_dir.is_dir():
|
||||
continue
|
||||
if not tool_dir.name.startswith("discussion-"):
|
||||
|
|
@ -183,7 +183,7 @@ def discover_participants(smarttools_dir: Path = None) -> list[Participant]:
|
|||
if not config_path.exists():
|
||||
continue
|
||||
|
||||
participant = _parse_smarttool_config(config_path)
|
||||
participant = _parse_cmdforge_config(config_path)
|
||||
if participant:
|
||||
participants.append(participant)
|
||||
|
||||
|
|
@ -192,7 +192,7 @@ def discover_participants(smarttools_dir: Path = None) -> list[Participant]:
|
|||
|
||||
def check_tool_exists(alias: str) -> bool:
|
||||
"""
|
||||
Check if a participant SmartTool exists and is callable.
|
||||
Check if a participant CmdForge tool exists and is callable.
|
||||
|
||||
Args:
|
||||
alias: Participant alias (e.g., "architect")
|
||||
|
|
@ -216,12 +216,12 @@ class ParticipantRegistry:
|
|||
"""
|
||||
Registry for discovered participants.
|
||||
|
||||
Discovers participants by scanning ~/.smarttools/ for SmartTools
|
||||
Discovers participants by scanning ~/.cmdforge/ for CmdForge tools
|
||||
matching the `discussion-{alias}` naming convention.
|
||||
"""
|
||||
|
||||
def __init__(self, smarttools_dir: Path = None):
|
||||
self._smarttools_dir = smarttools_dir
|
||||
def __init__(self, cmdforge_dir: Path = None):
|
||||
self._cmdforge_dir = cmdforge_dir
|
||||
self._participants: dict[str, Participant] = {}
|
||||
self._loaded = False
|
||||
|
||||
|
|
@ -230,7 +230,7 @@ class ParticipantRegistry:
|
|||
if self._loaded:
|
||||
return
|
||||
|
||||
for participant in discover_participants(self._smarttools_dir):
|
||||
for participant in discover_participants(self._cmdforge_dir):
|
||||
self._participants[participant.alias] = participant
|
||||
|
||||
self._loaded = True
|
||||
|
|
@ -332,7 +332,7 @@ def list_participants() -> list[Participant]:
|
|||
|
||||
def save_participant_settings(participant: Participant) -> bool:
|
||||
"""
|
||||
Save participant settings (voice, provider, color) back to SmartTool config.
|
||||
Save participant settings (voice, provider, color) back to CmdForge tool config.
|
||||
|
||||
Updates both the meta section and the prompt step provider.
|
||||
|
||||
|
|
@ -381,14 +381,14 @@ def save_participant_settings(participant: Participant) -> bool:
|
|||
|
||||
def get_available_providers() -> list[tuple[str, str]]:
|
||||
"""
|
||||
Get list of available AI providers from SmartTools.
|
||||
Get list of available AI providers from CmdForge.
|
||||
|
||||
Returns:
|
||||
List of (provider_name, description) tuples
|
||||
"""
|
||||
# Try to import from SmartTools
|
||||
# Try to import from CmdForge
|
||||
try:
|
||||
from smarttools.providers import load_providers
|
||||
from cmdforge.providers import load_providers
|
||||
providers = load_providers()
|
||||
return [(p.name, p.description) for p in providers]
|
||||
except ImportError:
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
"""
|
||||
Discussion runner - thin orchestration layer.
|
||||
|
||||
This module orchestrates SmartTools to execute discussion turns.
|
||||
It contains NO business logic - all logic lives in SmartTools.
|
||||
This module orchestrates CmdForge tools to execute discussion turns.
|
||||
It contains NO business logic - all logic lives in CmdForge tools.
|
||||
|
||||
The runner simply:
|
||||
1. Loads pipeline configuration from template
|
||||
2. Calls SmartTools via subprocess based on pipeline steps
|
||||
2. Calls CmdForge tools via subprocess based on pipeline steps
|
||||
3. Pipes data between tools
|
||||
4. Updates the discussion file
|
||||
|
||||
|
|
@ -81,7 +81,7 @@ DEFAULT_PIPELINE = {
|
|||
|
||||
@dataclass
|
||||
class ParticipantResponse:
|
||||
"""Response from a participant SmartTool."""
|
||||
"""Response from a participant CmdForge tool."""
|
||||
alias: str
|
||||
name: str
|
||||
comment: Optional[str] = None
|
||||
|
|
@ -118,7 +118,7 @@ class TurnResult:
|
|||
|
||||
def _call_tool(tool_name: str, input_data: str, args: list[str] = None, timeout: int = 300) -> subprocess.CompletedProcess:
|
||||
"""
|
||||
Call a SmartTool via subprocess.
|
||||
Call a CmdForge tool via subprocess.
|
||||
|
||||
Args:
|
||||
tool_name: Name of the tool (e.g., "discussion-parser")
|
||||
|
|
@ -399,7 +399,7 @@ def run_pipeline_turn(
|
|||
2. Executes each step by piping input -> tool -> output
|
||||
3. Returns results without any business logic
|
||||
|
||||
All logic lives in the SmartTools themselves.
|
||||
All logic lives in the CmdForge tools themselves.
|
||||
|
||||
Args:
|
||||
discussion_path: Path to discussion markdown file
|
||||
|
|
@ -739,7 +739,7 @@ def run_turn(
|
|||
provider: str = None,
|
||||
) -> TurnResult:
|
||||
"""
|
||||
Run a discussion turn by orchestrating SmartTools.
|
||||
Run a discussion turn by orchestrating CmdForge tools.
|
||||
|
||||
Pipeline:
|
||||
1. discussion-parser - Parse current state
|
||||
|
|
@ -775,7 +775,7 @@ def run_turn(
|
|||
raise RuntimeError(f"Parser failed: {parser_result.stderr}")
|
||||
state = _parse_json_output(parser_result.stdout)
|
||||
except FileNotFoundError:
|
||||
raise RuntimeError("discussion-parser not found. Is SmartTools installed?")
|
||||
raise RuntimeError("discussion-parser not found. Is CmdForge installed?")
|
||||
|
||||
current_status = state.get("metadata", {}).get("status", "OPEN")
|
||||
current_phase = state.get("metadata", {}).get("phase", "initial_feedback")
|
||||
|
|
|
|||
|
|
@ -290,19 +290,40 @@ class DiscussionGUI:
|
|||
def transcribe():
|
||||
transcript = ""
|
||||
try:
|
||||
if audio_file and os.path.exists(audio_file):
|
||||
transcribe_cmd = os.path.expanduser("~/.local/bin/transcribe")
|
||||
result = subprocess.run(
|
||||
[transcribe_cmd],
|
||||
input=audio_file,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=60
|
||||
)
|
||||
transcript = result.stdout.strip()
|
||||
if not audio_file:
|
||||
transcript = "[No audio file path]"
|
||||
elif not os.path.exists(audio_file):
|
||||
transcript = f"[Audio file not found: {audio_file}]"
|
||||
else:
|
||||
# Check file size to ensure recording happened
|
||||
file_size = os.path.getsize(audio_file)
|
||||
if file_size < 1000: # Less than 1KB likely means no audio
|
||||
transcript = "[Recording too short or empty]"
|
||||
else:
|
||||
transcribe_cmd = os.path.expanduser("~/.local/bin/transcribe")
|
||||
if not os.path.exists(transcribe_cmd):
|
||||
transcript = "[transcribe tool not found at ~/.local/bin/transcribe]"
|
||||
else:
|
||||
result = subprocess.run(
|
||||
[transcribe_cmd],
|
||||
input=audio_file,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=60
|
||||
)
|
||||
transcript = result.stdout.strip()
|
||||
if result.returncode != 0 and result.stderr:
|
||||
transcript = f"[Transcribe error: {result.stderr.strip()}]"
|
||||
elif not transcript:
|
||||
transcript = "[No speech detected]"
|
||||
|
||||
# Clean up audio file
|
||||
os.remove(audio_file)
|
||||
try:
|
||||
os.remove(audio_file)
|
||||
except Exception:
|
||||
pass
|
||||
except subprocess.TimeoutExpired:
|
||||
transcript = "[Transcription timed out after 60 seconds]"
|
||||
except Exception as e:
|
||||
transcript = f"[Transcription error: {e}]"
|
||||
|
||||
|
|
@ -318,7 +339,12 @@ class DiscussionGUI:
|
|||
if dpg.does_item_exist("dictate_btn"):
|
||||
dpg.set_item_label("dictate_btn", "Dictate")
|
||||
|
||||
if transcript and not transcript.startswith("["):
|
||||
if not transcript:
|
||||
self._show_error("Transcription returned empty result")
|
||||
elif transcript.startswith("["):
|
||||
# Error message from transcribe tool
|
||||
self._show_error(f"Transcription failed: {transcript}")
|
||||
else:
|
||||
# Append to existing comment text
|
||||
if dpg.does_item_exist("comment_text"):
|
||||
current = dpg.get_value("comment_text") or ""
|
||||
|
|
@ -2388,7 +2414,7 @@ class DiscussionGUI:
|
|||
personality = dpg.get_value("part_personality").strip()
|
||||
voice = dpg.get_value("part_voice") or (DEFAULT_VOICE if DEFAULT_VOICE else "en-US-Neural2-J")
|
||||
|
||||
# Build SmartTool config
|
||||
# Build CmdForge tool config
|
||||
import yaml
|
||||
config = {
|
||||
'name': f'discussion-{alias}',
|
||||
|
|
@ -2448,10 +2474,10 @@ final = json.dumps(parsed)''',
|
|||
'output': '{final}'
|
||||
}
|
||||
|
||||
# Save to ~/.smarttools/
|
||||
smarttools_dir = Path.home() / ".smarttools" / f"discussion-{alias}"
|
||||
smarttools_dir.mkdir(parents=True, exist_ok=True)
|
||||
config_path = smarttools_dir / "config.yaml"
|
||||
# Save to ~/.cmdforge/
|
||||
cmdforge_dir = Path.home() / ".cmdforge" / f"discussion-{alias}"
|
||||
cmdforge_dir.mkdir(parents=True, exist_ok=True)
|
||||
config_path = cmdforge_dir / "config.yaml"
|
||||
|
||||
if config_path.exists():
|
||||
self._show_error(f"Participant @{alias} already exists")
|
||||
|
|
@ -3272,7 +3298,7 @@ final = json.dumps(parsed)''',
|
|||
|
||||
def get_participant_path(alias: str) -> Path:
|
||||
"""Get the path to a participant config."""
|
||||
return Path.home() / ".smarttools" / f"discussion-{alias}" / "config.yaml"
|
||||
return Path.home() / ".cmdforge" / f"discussion-{alias}" / "config.yaml"
|
||||
|
||||
def select_participant(sender, app_data, user_data):
|
||||
"""Handle participant selection."""
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ Voting data structures and display helpers for Orchestrated Discussions.
|
|||
|
||||
NOTE: This module provides convenience functions for quick local display
|
||||
(CLI status, TUI widgets). The authoritative implementation lives in the
|
||||
`discussion-vote-counter` SmartTool, which is used by the runner pipeline.
|
||||
`discussion-vote-counter` CmdForge tool, which is used by the runner pipeline.
|
||||
|
||||
These implementations should stay in sync. If voting logic changes,
|
||||
update BOTH this file AND smarttools/discussion-vote-counter/config.yaml.
|
||||
update BOTH this file AND cmdforge/discussion-vote-counter/config.yaml.
|
||||
|
||||
See docs/DESIGN.md for voting rules specification.
|
||||
"""
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -4,7 +4,7 @@
|
|||
name: feature
|
||||
description: Feature proposal and review workflow
|
||||
|
||||
# Turn pipeline - defines what SmartTools run during each turn
|
||||
# Turn pipeline - defines what CmdForge tools run during each turn
|
||||
# Uses variable-based schema: $input -> tool -> $output
|
||||
turn_pipeline:
|
||||
steps:
|
||||
|
|
|
|||
Loading…
Reference in New Issue