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:
rob 2026-01-04 02:15:24 -04:00
parent a39253c893
commit 55aec4c7f2
41 changed files with 285 additions and 243 deletions

View File

@ -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.

View File

@ -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

View File

@ -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/"]

View File

@ -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)

View File

@ -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

View File

@ -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:

View File

@ -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:

View File

@ -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)

View File

@ -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

View File

@ -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.*

View File

@ -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]

View File

@ -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.
#

View File

@ -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

View File

@ -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:

View File

@ -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")

View File

@ -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."""

View File

@ -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

View File

@ -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: