docs: update PlantUML diagrams for multi-provider fallback and regex marker extraction
- Updated commit-workflow.puml to show claude→codex→gemini fallback chain - Updated patcher-pipeline.puml with provider fallback logic and model hints - Updated voting-system.puml for multi-stage promotions (READY_FOR_DESIGN) - Created ai-provider-fallback.puml documenting provider chain in detail - Created discussion-stages.puml showing complete feature lifecycle - Created workflow-marker-extraction.puml documenting regex patterns - Updated diagrams-README.md with all new diagrams and workflows - Increased diagram count from 7 to 10 total - All diagrams now reflect current system architecture 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
0601117371
commit
038dbe8a3e
|
|
@ -0,0 +1,163 @@
|
||||||
|
@startuml ai-provider-fallback
|
||||||
|
!theme plain
|
||||||
|
title AI Provider Fallback Chain with Model Hints
|
||||||
|
|
||||||
|
start
|
||||||
|
|
||||||
|
:Automation needs AI generation\n(from patcher.py or runner.py);
|
||||||
|
|
||||||
|
:Read config/ai.yml;
|
||||||
|
|
||||||
|
if (Rule has model_hint?) then (yes)
|
||||||
|
if (model_hint == "fast"?) then (yes)
|
||||||
|
:Use **command_chain_fast**:
|
||||||
|
- claude -p (→ Haiku subagent)
|
||||||
|
- codex --model gpt-5-mini
|
||||||
|
- gemini --model gemini-2.5-flash;
|
||||||
|
else if (model_hint == "quality"?) then (yes)
|
||||||
|
:Use **command_chain_quality**:
|
||||||
|
- claude -p (→ Sonnet subagent)
|
||||||
|
- codex --model o3
|
||||||
|
- gemini --model gemini-2.5-pro;
|
||||||
|
else (unknown hint)
|
||||||
|
:Fall back to default chain;
|
||||||
|
endif
|
||||||
|
else (no hint)
|
||||||
|
:Use **command_chain** (default):
|
||||||
|
- claude -p (→ auto-select subagent)
|
||||||
|
- codex --model gpt-5
|
||||||
|
- gemini --model gemini-2.5-flash;
|
||||||
|
endif
|
||||||
|
|
||||||
|
partition "Provider Loop" {
|
||||||
|
:Get next provider from chain;
|
||||||
|
|
||||||
|
if (Provider == "claude"?) then (yes)
|
||||||
|
:Execute: **claude -p**;
|
||||||
|
note right
|
||||||
|
Claude CLI uses TASK COMPLEXITY hint
|
||||||
|
from prompt to select subagent:
|
||||||
|
- FAST → cdev-patch (Haiku)
|
||||||
|
- QUALITY → cdev-patch-quality (Sonnet)
|
||||||
|
- Default → auto-select
|
||||||
|
end note
|
||||||
|
|
||||||
|
if (Returned output?) then (yes)
|
||||||
|
if (Contains diff markers?) then (yes)
|
||||||
|
:✓ Success! Extract diff;
|
||||||
|
stop
|
||||||
|
else (no - non-diff response)
|
||||||
|
:Log: "Claude non-diff output";
|
||||||
|
:Try next provider;
|
||||||
|
endif
|
||||||
|
else (command failed)
|
||||||
|
:Log: "Claude command failed";
|
||||||
|
:Try next provider;
|
||||||
|
endif
|
||||||
|
|
||||||
|
else if (Provider == "codex"?) then (yes)
|
||||||
|
:Execute: **codex exec --model X --json -**;
|
||||||
|
note right
|
||||||
|
Codex requires special handling:
|
||||||
|
- Add "exec" subcommand
|
||||||
|
- Add "--json" flag
|
||||||
|
- Add "--color=never"
|
||||||
|
- Add "-" to read from stdin
|
||||||
|
- Parse JSON output for agent_message
|
||||||
|
end note
|
||||||
|
|
||||||
|
if (Exit code == 0?) then (yes)
|
||||||
|
:Parse JSON lines;
|
||||||
|
:Extract agent_message text;
|
||||||
|
|
||||||
|
if (Contains diff?) then (yes)
|
||||||
|
:✓ Success! Extract diff;
|
||||||
|
stop
|
||||||
|
else (no diff)
|
||||||
|
:Log: "Codex no diff output";
|
||||||
|
:Try next provider;
|
||||||
|
endif
|
||||||
|
else (exit code 1)
|
||||||
|
:Log: "Codex exited with 1";
|
||||||
|
:Try next provider;
|
||||||
|
endif
|
||||||
|
|
||||||
|
else if (Provider == "gemini"?) then (yes)
|
||||||
|
:Execute: **gemini --model X**;
|
||||||
|
note right
|
||||||
|
Gemini is the most reliable fallback:
|
||||||
|
- Accepts plain text input
|
||||||
|
- Returns consistent output
|
||||||
|
- Supports sentinel token
|
||||||
|
end note
|
||||||
|
|
||||||
|
if (Returned output?) then (yes)
|
||||||
|
if (Output == sentinel token?) then (yes)
|
||||||
|
:Log: "No changes needed";
|
||||||
|
:Return empty (intentional);
|
||||||
|
stop
|
||||||
|
else if (Contains diff?) then (yes)
|
||||||
|
:✓ Success! Extract diff;
|
||||||
|
stop
|
||||||
|
else (no diff)
|
||||||
|
:Log: "Gemini no diff output";
|
||||||
|
:Try next provider;
|
||||||
|
endif
|
||||||
|
else (command failed)
|
||||||
|
:Log: "Gemini command failed";
|
||||||
|
:Try next provider;
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
if (More providers in chain?) then (yes)
|
||||||
|
:Continue loop;
|
||||||
|
else (no)
|
||||||
|
:✗ All providers failed;
|
||||||
|
:Raise PatchGenerationError;
|
||||||
|
stop
|
||||||
|
endif
|
||||||
|
}
|
||||||
|
|
||||||
|
stop
|
||||||
|
|
||||||
|
legend bottom
|
||||||
|
**Configuration Example (config/ai.yml):**
|
||||||
|
|
||||||
|
runner:
|
||||||
|
command_chain:
|
||||||
|
- "claude -p"
|
||||||
|
- "codex --model gpt-5"
|
||||||
|
- "gemini --model gemini-2.5-flash"
|
||||||
|
|
||||||
|
command_chain_fast:
|
||||||
|
- "claude -p"
|
||||||
|
- "codex --model gpt-5-mini"
|
||||||
|
- "gemini --model gemini-2.5-flash"
|
||||||
|
|
||||||
|
command_chain_quality:
|
||||||
|
- "claude -p"
|
||||||
|
- "codex --model o3"
|
||||||
|
- "gemini --model gemini-2.5-pro"
|
||||||
|
|
||||||
|
sentinel: "CASCADINGDEV_NO_CHANGES"
|
||||||
|
|
||||||
|
**Environment Override:**
|
||||||
|
export CDEV_AI_COMMAND="claude -p || gemini --model gemini-2.5-pro"
|
||||||
|
(Overrides config.yml for this commit only)
|
||||||
|
endlegend
|
||||||
|
|
||||||
|
note right
|
||||||
|
**Why Fallback Chain?**
|
||||||
|
|
||||||
|
1. **Redundancy**: Rate limits, API outages
|
||||||
|
2. **Model specialization**: Different models excel at different tasks
|
||||||
|
3. **Cost optimization**: Try cheaper models first
|
||||||
|
4. **Quality assurance**: Fast models for simple tasks, quality for complex
|
||||||
|
|
||||||
|
**Observed Behavior:**
|
||||||
|
- Claude occasionally returns non-diff output
|
||||||
|
- Codex consistently exits with code 1 (auth issues?)
|
||||||
|
- Gemini is the most reliable fallback
|
||||||
|
end note
|
||||||
|
|
||||||
|
@enduml
|
||||||
|
|
@ -8,7 +8,10 @@ participant "pre-commit hook" as hook
|
||||||
participant "runner.py" as runner
|
participant "runner.py" as runner
|
||||||
participant "config.py" as config
|
participant "config.py" as config
|
||||||
participant "patcher.py" as patcher
|
participant "patcher.py" as patcher
|
||||||
participant "Claude API" as claude
|
participant "AI Providers" as ai
|
||||||
|
participant "Claude CLI" as claude
|
||||||
|
participant "Codex CLI" as codex
|
||||||
|
participant "Gemini CLI" as gemini
|
||||||
participant "workflow.py" as workflow
|
participant "workflow.py" as workflow
|
||||||
database ".git index" as index
|
database ".git index" as index
|
||||||
|
|
||||||
|
|
@ -35,22 +38,57 @@ loop For each staged file
|
||||||
activate patcher
|
activate patcher
|
||||||
|
|
||||||
patcher -> patcher: Build prompt with\nsource diff + context
|
patcher -> patcher: Build prompt with\nsource diff + context
|
||||||
patcher -> claude: Send prompt
|
|
||||||
|
patcher -> ai: Try provider 1/3
|
||||||
|
activate ai
|
||||||
|
ai -> claude: Send prompt
|
||||||
activate claude
|
activate claude
|
||||||
|
|
||||||
alt API Success
|
alt Claude produces diff
|
||||||
claude -> patcher: Return unified diff\n(wrapped in markers)
|
claude -> ai: Return unified diff\n(wrapped in markers)
|
||||||
|
ai -> patcher: Success with diff
|
||||||
|
deactivate claude
|
||||||
|
deactivate ai
|
||||||
patcher -> patcher: Extract & sanitize patch
|
patcher -> patcher: Extract & sanitize patch
|
||||||
patcher -> patcher: git apply --3way
|
patcher -> patcher: git apply --3way
|
||||||
patcher -> index: Stage generated file
|
patcher -> index: Stage generated file
|
||||||
patcher -> runner: Success
|
patcher -> runner: Success
|
||||||
else API Overload/Error
|
else Claude non-diff output
|
||||||
claude -> patcher: Error response
|
claude -> ai: Non-diff response
|
||||||
|
deactivate claude
|
||||||
|
ai -> codex: Try provider 2/3
|
||||||
|
activate codex
|
||||||
|
|
||||||
|
alt Codex succeeds
|
||||||
|
codex -> ai: Return diff (JSON parsed)
|
||||||
|
deactivate codex
|
||||||
|
deactivate ai
|
||||||
|
patcher -> patcher: Extract & sanitize
|
||||||
|
patcher -> index: Stage file
|
||||||
|
patcher -> runner: Success
|
||||||
|
else Codex fails (exit 1)
|
||||||
|
codex -> ai: Exit code 1
|
||||||
|
deactivate codex
|
||||||
|
ai -> gemini: Try provider 3/3
|
||||||
|
activate gemini
|
||||||
|
|
||||||
|
alt Gemini succeeds
|
||||||
|
gemini -> ai: Return diff
|
||||||
|
deactivate gemini
|
||||||
|
deactivate ai
|
||||||
|
patcher -> patcher: Extract & sanitize
|
||||||
|
patcher -> index: Stage file
|
||||||
|
patcher -> runner: Success
|
||||||
|
else All providers failed
|
||||||
|
gemini -> ai: Error/no diff
|
||||||
|
deactivate gemini
|
||||||
|
deactivate ai
|
||||||
patcher -> patcher: Log error to stderr
|
patcher -> patcher: Log error to stderr
|
||||||
patcher -> runner: Skip this file
|
patcher -> runner: Skip this file
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
deactivate claude
|
|
||||||
deactivate patcher
|
deactivate patcher
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -73,15 +111,38 @@ git -> index: Create commit
|
||||||
git -> Developer: Commit successful
|
git -> Developer: Commit successful
|
||||||
deactivate git
|
deactivate git
|
||||||
|
|
||||||
|
note right of ai
|
||||||
|
**Multi-Provider Fallback Chain**
|
||||||
|
Configured in config/ai.yml:
|
||||||
|
1. claude -p (Claude CLI with subagent)
|
||||||
|
2. codex exec --model gpt-5 --json
|
||||||
|
3. gemini --model gemini-2.5-flash
|
||||||
|
|
||||||
|
Each provider tried until one succeeds.
|
||||||
|
Provides redundancy against:
|
||||||
|
- Rate limits
|
||||||
|
- API outages
|
||||||
|
- Non-diff responses
|
||||||
|
end note
|
||||||
|
|
||||||
note right of patcher
|
note right of patcher
|
||||||
Saves debug artifacts to
|
Saves debug artifacts to
|
||||||
.git/ai-rules-debug/
|
.git/ai-rules-debug/
|
||||||
for troubleshooting
|
for troubleshooting:
|
||||||
|
- *.raw.out
|
||||||
|
- *.clean.diff
|
||||||
|
- *.sanitized.diff
|
||||||
|
- *.final.diff
|
||||||
end note
|
end note
|
||||||
|
|
||||||
note right of workflow
|
note right of workflow
|
||||||
Always exits 0
|
Always exits 0
|
||||||
(non-blocking)
|
(non-blocking)
|
||||||
|
|
||||||
|
Extracts structured markers:
|
||||||
|
- **DECISION**: text
|
||||||
|
- **QUESTION**: text
|
||||||
|
- **ACTION**: @assignee text
|
||||||
end note
|
end note
|
||||||
|
|
||||||
@enduml
|
@enduml
|
||||||
|
|
|
||||||
|
|
@ -39,18 +39,18 @@ plantuml -tsvg docs/*.puml
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 2. **commit-workflow.puml**
|
### 2. **commit-workflow.puml** ⭐ UPDATED
|
||||||
**Sequence diagram** of what happens during `git commit`.
|
**Sequence diagram** of what happens during `git commit` with multi-provider fallback.
|
||||||
|
|
||||||
**Shows:**
|
**Shows:**
|
||||||
- Pre-commit hook execution
|
- Pre-commit hook execution
|
||||||
- runner.py orchestration
|
- runner.py orchestration
|
||||||
- AI API calls
|
- Multi-provider AI fallback (claude → codex → gemini)
|
||||||
- Patch generation and application
|
- Patch generation and application
|
||||||
- Vote processing
|
- Vote processing with marker extraction
|
||||||
- File staging
|
- File staging
|
||||||
|
|
||||||
**Best for:** Understanding the complete commit-time automation flow.
|
**Best for:** Understanding the complete commit-time automation flow with provider redundancy.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -67,33 +67,34 @@ plantuml -tsvg docs/*.puml
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 4. **patcher-pipeline.puml**
|
### 4. **patcher-pipeline.puml** ⭐ UPDATED
|
||||||
**Detailed flowchart** of AI patch generation and application.
|
**Detailed flowchart** of AI patch generation and application with provider fallback.
|
||||||
|
|
||||||
**Shows:**
|
**Shows:**
|
||||||
- Prompt building
|
- Prompt building with model hints
|
||||||
- AI command execution
|
- Multi-provider fallback logic (claude → codex → gemini)
|
||||||
|
- Codex JSON parsing
|
||||||
- Patch extraction (with markers)
|
- Patch extraction (with markers)
|
||||||
- Patch sanitization
|
- Patch sanitization
|
||||||
- git apply strategies (strict → 3-way → fallback)
|
- git apply strategies (strict → 3-way → fallback)
|
||||||
- Debug artifact saving
|
- Debug artifact saving
|
||||||
- Error handling
|
- Error handling
|
||||||
|
|
||||||
**Best for:** Debugging patch application issues or understanding the AI integration.
|
**Best for:** Debugging patch application issues or understanding the AI provider chain.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 5. **voting-system.puml**
|
### 5. **voting-system.puml** ⭐ UPDATED
|
||||||
**Voting and promotion logic** for feature discussions.
|
**Voting and promotion logic** for multi-stage feature discussions.
|
||||||
|
|
||||||
**Shows:**
|
**Shows:**
|
||||||
- Vote parsing from discussion files
|
- Vote parsing from discussion files
|
||||||
- Eligible voter calculation
|
- Eligible voter calculation
|
||||||
- Promotion thresholds (READY_FOR_IMPLEMENTATION)
|
- Stage-specific promotion thresholds (READY_FOR_DESIGN, READY_FOR_IMPLEMENTATION, etc.)
|
||||||
- Rejection logic
|
- Rejection logic per stage
|
||||||
- Summary file updates
|
- Summary file updates
|
||||||
|
|
||||||
**Best for:** Understanding how features move through approval stages.
|
**Best for:** Understanding how features move through multi-stage approval (feature → design → implementation → review).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -125,20 +126,72 @@ plantuml -tsvg docs/*.puml
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### 8. **ai-provider-fallback.puml** 🆕
|
||||||
|
**Detailed flowchart** of the multi-provider AI fallback chain with model hints.
|
||||||
|
|
||||||
|
**Shows:**
|
||||||
|
- Command chain selection (default, fast, quality)
|
||||||
|
- Model hint propagation (TASK COMPLEXITY)
|
||||||
|
- Provider-specific execution (Claude CLI, Codex JSON, Gemini)
|
||||||
|
- Fallback logic (claude → codex → gemini)
|
||||||
|
- Sentinel token handling
|
||||||
|
- Error handling per provider
|
||||||
|
|
||||||
|
**Best for:** Understanding how AI provider redundancy works and debugging provider failures.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 9. **discussion-stages.puml** 🆕
|
||||||
|
**State machine diagram** showing the complete feature discussion lifecycle through all stages.
|
||||||
|
|
||||||
|
**Shows:**
|
||||||
|
- Feature stage (OPEN → READY_FOR_DESIGN)
|
||||||
|
- Design stage (OPEN → READY_FOR_IMPLEMENTATION)
|
||||||
|
- Implementation stage (IN_PROGRESS → READY_FOR_REVIEW)
|
||||||
|
- Review stage (UNDER_REVIEW → APPROVED)
|
||||||
|
- Status transitions and promotion conditions
|
||||||
|
- Auto-generated files per stage
|
||||||
|
|
||||||
|
**Best for:** Understanding the full feature approval workflow from request to merge.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 10. **workflow-marker-extraction.puml** 🆕
|
||||||
|
**Detailed flowchart** of regex-based marker extraction from discussion files.
|
||||||
|
|
||||||
|
**Shows:**
|
||||||
|
- Comment parsing from discussion files
|
||||||
|
- Regex pattern matching for **DECISION**, **QUESTION**, **ACTION**
|
||||||
|
- Support for both plain (DECISION:) and markdown bold (**DECISION**:) formats
|
||||||
|
- Structured data extraction
|
||||||
|
- Summary section generation
|
||||||
|
- Marker block updates in .sum.md files
|
||||||
|
|
||||||
|
**Best for:** Understanding how structured markers are extracted and why regex was chosen over line-start matching.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Key Concepts Illustrated
|
## Key Concepts Illustrated
|
||||||
|
|
||||||
### Automation Pipeline
|
### Automation Pipeline
|
||||||
```
|
```
|
||||||
Developer commits → Pre-commit hook → runner.py → patcher.py → Claude API
|
Developer commits → Pre-commit hook → runner.py → patcher.py → Multi-Provider AI
|
||||||
→ config.py → .ai-rules.yml
|
→ config.py → .ai-rules.yml (claude → codex → gemini)
|
||||||
→ workflow.py → summary.py
|
→ workflow.py → summary.py
|
||||||
|
(regex marker extraction)
|
||||||
```
|
```
|
||||||
|
|
||||||
### File Processing
|
### File Processing (Multi-Stage)
|
||||||
```
|
```
|
||||||
request.md (edited) → AI generates → feature.discussion.md (created/updated)
|
request.md (edited) → AI generates → feature.discussion.md (created/updated)
|
||||||
→ feature.discussion.sum.md (updated)
|
→ feature.discussion.sum.md (updated)
|
||||||
→ implementation.discussion.md (gated)
|
↓ (votes → READY_FOR_DESIGN)
|
||||||
|
→ design.discussion.md (created)
|
||||||
|
→ design.discussion.sum.md (updated)
|
||||||
|
↓ (votes → READY_FOR_IMPLEMENTATION)
|
||||||
|
→ implementation.discussion.md (created)
|
||||||
|
↓ (votes → READY_FOR_REVIEW)
|
||||||
|
→ review.discussion.md (created)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Voting Flow
|
### Voting Flow
|
||||||
|
|
@ -171,9 +224,21 @@ Patch fails → Save debug artifacts → Log error → Continue
|
||||||
3. Review **commit-workflow.puml** for execution order
|
3. Review **commit-workflow.puml** for execution order
|
||||||
|
|
||||||
### Understanding Status Transitions
|
### Understanding Status Transitions
|
||||||
1. See **voting-system.puml** for promotion logic
|
1. See **discussion-stages.puml** for complete multi-stage flow
|
||||||
2. Check **file-lifecycle.puml** for state machine
|
2. See **voting-system.puml** for promotion logic per stage
|
||||||
3. Review discussion file YAML headers for thresholds
|
3. Check **file-lifecycle.puml** for developer workflow
|
||||||
|
4. Review discussion file YAML headers for thresholds
|
||||||
|
|
||||||
|
### Understanding AI Provider System
|
||||||
|
1. See **ai-provider-fallback.puml** for provider chain logic
|
||||||
|
2. Check **patcher-pipeline.puml** for integration details
|
||||||
|
3. Review config/ai.yml for command configuration
|
||||||
|
4. Check .git/ai-rules-debug/ for provider outputs
|
||||||
|
|
||||||
|
### Understanding Marker Extraction
|
||||||
|
1. See **workflow-marker-extraction.puml** for regex patterns
|
||||||
|
2. Review automation/workflow.py for implementation
|
||||||
|
3. Test with **DECISION**, **QUESTION**, **ACTION** markers in discussions
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -183,8 +248,12 @@ Patch fails → Save debug artifacts → Log error → Continue
|
||||||
|---------|--------|---------|
|
|---------|--------|---------|
|
||||||
| Cascading Rules | ✅ Complete | cascading-rules.puml |
|
| Cascading Rules | ✅ Complete | cascading-rules.puml |
|
||||||
| AI Patch Generation | ✅ Complete | patcher-pipeline.puml |
|
| AI Patch Generation | ✅ Complete | patcher-pipeline.puml |
|
||||||
|
| Multi-Provider Fallback | ✅ Complete | ai-provider-fallback.puml |
|
||||||
|
| Model Hints (fast/quality) | ✅ Complete | ai-provider-fallback.puml |
|
||||||
| Vote Tracking | ✅ Complete | voting-system.puml |
|
| Vote Tracking | ✅ Complete | voting-system.puml |
|
||||||
| Promotion Logic | ✅ Complete | voting-system.puml |
|
| Multi-Stage Promotion | ✅ Complete | discussion-stages.puml |
|
||||||
|
| Regex Marker Extraction | ✅ Complete | workflow-marker-extraction.puml |
|
||||||
|
| Structured Summaries | ✅ Complete | workflow-marker-extraction.puml |
|
||||||
| Implementation Gate | ✅ Complete | file-lifecycle.puml |
|
| Implementation Gate | ✅ Complete | file-lifecycle.puml |
|
||||||
| Error Handling | ✅ Complete | commit-workflow.puml |
|
| Error Handling | ✅ Complete | commit-workflow.puml |
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,148 @@
|
||||||
|
@startuml discussion-stages
|
||||||
|
!theme plain
|
||||||
|
title Feature Discussion Stage Progression with Status Transitions
|
||||||
|
|
||||||
|
state "Feature Stage" as feature {
|
||||||
|
[*] --> OPEN_F : feature.discussion.md created
|
||||||
|
|
||||||
|
OPEN_F : status: OPEN
|
||||||
|
OPEN_F : Participants discuss scope,\nplatform, requirements
|
||||||
|
|
||||||
|
OPEN_F --> READY_FOR_DESIGN : ≥2 READY votes\n(human only if\nallow_agent_votes: false)
|
||||||
|
|
||||||
|
READY_FOR_DESIGN : status: READY_FOR_DESIGN
|
||||||
|
READY_FOR_DESIGN : Scope approved,\nready for technical design
|
||||||
|
|
||||||
|
READY_FOR_DESIGN --> FEATURE_REJECTED : Majority REJECT votes
|
||||||
|
FEATURE_REJECTED : status: FEATURE_REJECTED
|
||||||
|
FEATURE_REJECTED : Feature blocked
|
||||||
|
|
||||||
|
note right of READY_FOR_DESIGN
|
||||||
|
**AI Auto-generates:**
|
||||||
|
design.discussion.md
|
||||||
|
(Initial design proposal)
|
||||||
|
end note
|
||||||
|
}
|
||||||
|
|
||||||
|
state "Design Stage" as design {
|
||||||
|
[*] --> OPEN_D : design.discussion.md created
|
||||||
|
|
||||||
|
OPEN_D : status: OPEN
|
||||||
|
OPEN_D : Discuss architecture,\ntech stack, data models
|
||||||
|
|
||||||
|
OPEN_D --> READY_FOR_IMPLEMENTATION : ≥2 READY votes
|
||||||
|
READY_FOR_IMPLEMENTATION : status: READY_FOR_IMPLEMENTATION
|
||||||
|
READY_FOR_IMPLEMENTATION : Design approved,\nready to implement
|
||||||
|
|
||||||
|
OPEN_D --> DESIGN_REJECTED : Majority REJECT votes
|
||||||
|
DESIGN_REJECTED : status: DESIGN_REJECTED
|
||||||
|
DESIGN_REJECTED : Design needs rework
|
||||||
|
|
||||||
|
note right of READY_FOR_IMPLEMENTATION
|
||||||
|
**AI Auto-generates:**
|
||||||
|
implementation.discussion.md
|
||||||
|
(Implementation tracking)
|
||||||
|
end note
|
||||||
|
}
|
||||||
|
|
||||||
|
state "Implementation Stage" as impl {
|
||||||
|
[*] --> IN_PROGRESS : implementation.discussion.md created
|
||||||
|
|
||||||
|
IN_PROGRESS : status: IN_PROGRESS
|
||||||
|
IN_PROGRESS : Track tasks,\ncode progress,\nblocking issues
|
||||||
|
|
||||||
|
IN_PROGRESS --> READY_FOR_REVIEW : All tasks completed\n≥2 READY votes
|
||||||
|
|
||||||
|
READY_FOR_REVIEW : status: READY_FOR_REVIEW
|
||||||
|
READY_FOR_REVIEW : Implementation complete
|
||||||
|
|
||||||
|
note right of READY_FOR_REVIEW
|
||||||
|
**AI Auto-generates:**
|
||||||
|
review.discussion.md
|
||||||
|
(Code review tracking)
|
||||||
|
end note
|
||||||
|
}
|
||||||
|
|
||||||
|
state "Review Stage" as review {
|
||||||
|
[*] --> UNDER_REVIEW : review.discussion.md created
|
||||||
|
|
||||||
|
UNDER_REVIEW : status: UNDER_REVIEW
|
||||||
|
UNDER_REVIEW : Code review,\ntesting, QA
|
||||||
|
|
||||||
|
UNDER_REVIEW --> APPROVED : ≥2 READY votes
|
||||||
|
UNDER_REVIEW --> NEEDS_CHANGES : CHANGES votes
|
||||||
|
|
||||||
|
APPROVED : status: APPROVED
|
||||||
|
APPROVED : Ready to merge
|
||||||
|
|
||||||
|
NEEDS_CHANGES --> UNDER_REVIEW : Changes addressed
|
||||||
|
}
|
||||||
|
|
||||||
|
[*] --> feature
|
||||||
|
READY_FOR_DESIGN --> design
|
||||||
|
READY_FOR_IMPLEMENTATION --> impl
|
||||||
|
READY_FOR_REVIEW --> review
|
||||||
|
APPROVED --> [*]
|
||||||
|
|
||||||
|
legend bottom
|
||||||
|
**Vote Counting Rules (Configured per stage):**
|
||||||
|
|
||||||
|
promotion_rule:
|
||||||
|
allow_agent_votes: false # Only count human votes
|
||||||
|
ready_min_eligible_votes: 2 # Need 2 READY to promote
|
||||||
|
reject_min_eligible_votes: 1 # Need 1 REJECT to block
|
||||||
|
|
||||||
|
**Vote Format in Discussion Files:**
|
||||||
|
ParticipantName: Comment text. VOTE: READY|CHANGES|REJECT
|
||||||
|
AI_BotName: Comment text. VOTE: CHANGES (excluded if allow_agent_votes: false)
|
||||||
|
|
||||||
|
**Status Transitions:**
|
||||||
|
- Automatic when vote thresholds met
|
||||||
|
- AI updates YAML header: status: field
|
||||||
|
- AI appends consensus comment
|
||||||
|
- Triggers next stage discussion creation
|
||||||
|
|
||||||
|
**Example Progression:**
|
||||||
|
1. Feature discussion: Define WHAT we're building
|
||||||
|
2. Design discussion: Define HOW we'll build it
|
||||||
|
3. Implementation discussion: Track building progress
|
||||||
|
4. Review discussion: Verify quality before merge
|
||||||
|
endlegend
|
||||||
|
|
||||||
|
note right of feature
|
||||||
|
**Participants Use Structured Markers:**
|
||||||
|
**DECISION**: Web platform, React frontend
|
||||||
|
**QUESTION**: Mobile support in MVP?
|
||||||
|
**ACTION**: @Alice research auth options
|
||||||
|
|
||||||
|
These are extracted to .sum.md files
|
||||||
|
for easy reference
|
||||||
|
end note
|
||||||
|
|
||||||
|
note right of design
|
||||||
|
**Design Decisions Tracked:**
|
||||||
|
- Architecture choices
|
||||||
|
- Technology stack
|
||||||
|
- Data models
|
||||||
|
- API contracts
|
||||||
|
- Risk trade-offs
|
||||||
|
end note
|
||||||
|
|
||||||
|
note right of impl
|
||||||
|
**Implementation Tracking:**
|
||||||
|
- Task breakdowns
|
||||||
|
- Blocking issues
|
||||||
|
- Progress updates
|
||||||
|
- Code references
|
||||||
|
end note
|
||||||
|
|
||||||
|
note right of review
|
||||||
|
**Review Checklist:**
|
||||||
|
- Code quality
|
||||||
|
- Test coverage
|
||||||
|
- Documentation
|
||||||
|
- Performance
|
||||||
|
- Security
|
||||||
|
end note
|
||||||
|
|
||||||
|
@enduml
|
||||||
|
|
@ -10,17 +10,55 @@ start
|
||||||
- Source file diff (staged changes)
|
- Source file diff (staged changes)
|
||||||
- Source file full content
|
- Source file full content
|
||||||
- Target file current content
|
- Target file current content
|
||||||
- Generation instructions from rules;
|
- Generation instructions from rules
|
||||||
|
- Model hint (fast/quality) if specified;
|
||||||
|
|
||||||
:Call AI via shell command
|
partition "Multi-Provider Fallback" {
|
||||||
(configured via git config or env);
|
:Try Provider 1: Claude CLI;
|
||||||
|
|
||||||
if (AI returned output?) then (yes)
|
|
||||||
if (Output contains\n"API Error: Overloaded"?) then (yes)
|
if (Output contains\n"API Error: Overloaded"?) then (yes)
|
||||||
:Raise PatchGenerationError\n"Claude API is overloaded";
|
:Raise PatchGenerationError\n"Claude API is overloaded";
|
||||||
stop
|
stop
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if (Output contains diff markers?) then (yes)
|
||||||
|
:Success! Continue to extraction;
|
||||||
|
else (no - non-diff response)
|
||||||
|
:Log: "Claude non-diff output";
|
||||||
|
:Try Provider 2: Codex CLI;
|
||||||
|
|
||||||
|
if (Codex returned output?) then (yes)
|
||||||
|
:Parse JSON response\nextract agent_message;
|
||||||
|
|
||||||
|
if (Parsed text contains diff?) then (yes)
|
||||||
|
:Success! Continue to extraction;
|
||||||
|
else (no - exit code 1)
|
||||||
|
:Log: "Codex exited with 1";
|
||||||
|
:Try Provider 3: Gemini CLI;
|
||||||
|
|
||||||
|
if (Gemini returned output?) then (yes)
|
||||||
|
if (Gemini returned sentinel?) then (yes)
|
||||||
|
:Log: "No changes needed";
|
||||||
|
stop
|
||||||
|
else (has diff)
|
||||||
|
:Success! Continue to extraction;
|
||||||
|
endif
|
||||||
|
else (no)
|
||||||
|
:Raise "All providers failed";
|
||||||
|
stop
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
else (no)
|
||||||
|
:Raise "All providers failed";
|
||||||
|
stop
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
else (no - command failed)
|
||||||
|
:Raise "Provider 1 command failed";
|
||||||
|
stop
|
||||||
|
endif
|
||||||
|
}
|
||||||
|
|
||||||
:Save raw output to\n.git/ai-rules-debug/*.raw.out;
|
:Save raw output to\n.git/ai-rules-debug/*.raw.out;
|
||||||
|
|
||||||
if (Output contains\n<<<AI_DIFF_START>>>?) then (yes)
|
if (Output contains\n<<<AI_DIFF_START>>>?) then (yes)
|
||||||
|
|
@ -33,10 +71,6 @@ if (AI returned output?) then (yes)
|
||||||
stop
|
stop
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
else (no)
|
|
||||||
:Raise "AI command failed";
|
|
||||||
stop
|
|
||||||
endif
|
|
||||||
|
|
||||||
:Save to *.clean.diff;
|
:Save to *.clean.diff;
|
||||||
|
|
||||||
|
|
@ -87,6 +121,17 @@ endif
|
||||||
stop
|
stop
|
||||||
|
|
||||||
note right
|
note right
|
||||||
|
**AI Provider Configuration:**
|
||||||
|
config/ai.yml defines fallback chains:
|
||||||
|
- command_chain (default)
|
||||||
|
- command_chain_fast (model_hint: fast)
|
||||||
|
- command_chain_quality (model_hint: quality)
|
||||||
|
|
||||||
|
**Provider Details:**
|
||||||
|
1. Claude: claude -p (auto-selects subagent)
|
||||||
|
2. Codex: codex exec --model gpt-5 --json
|
||||||
|
3. Gemini: gemini --model gemini-2.5-flash
|
||||||
|
|
||||||
**Debug Artifacts Location:**
|
**Debug Artifacts Location:**
|
||||||
.git/ai-rules-debug/
|
.git/ai-rules-debug/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,15 +44,28 @@ partition "Promotion Logic (AI-powered)" {
|
||||||
:Count CHANGES votes (neutral);
|
:Count CHANGES votes (neutral);
|
||||||
|
|
||||||
if (READY threshold met AND\nREJECT threshold NOT met?) then (yes)
|
if (READY threshold met AND\nREJECT threshold NOT met?) then (yes)
|
||||||
|
if (Current stage == feature?) then (yes)
|
||||||
|
:Update status to\n**READY_FOR_DESIGN**;
|
||||||
|
:AI generates\ndesign.discussion.md;
|
||||||
|
else if (Current stage == design?) then (yes)
|
||||||
:Update status to\n**READY_FOR_IMPLEMENTATION**;
|
:Update status to\n**READY_FOR_IMPLEMENTATION**;
|
||||||
|
|
||||||
if (implementation_gate output defined?) then (yes)
|
|
||||||
:AI generates\nimplementation.discussion.md;
|
:AI generates\nimplementation.discussion.md;
|
||||||
|
else if (Current stage == implementation?) then (yes)
|
||||||
|
:Update status to\n**READY_FOR_REVIEW**;
|
||||||
|
:AI generates\nreview.discussion.md;
|
||||||
|
else (review stage)
|
||||||
|
:Update status to\n**APPROVED**;
|
||||||
endif
|
endif
|
||||||
else if (REJECT threshold met AND\nREADY threshold NOT met?) then (no)
|
else if (REJECT threshold met AND\nREADY threshold NOT met?) then (no)
|
||||||
|
if (Current stage == feature?) then (yes)
|
||||||
:Update status to\n**FEATURE_REJECTED**;
|
:Update status to\n**FEATURE_REJECTED**;
|
||||||
|
else if (Current stage == design?) then (yes)
|
||||||
|
:Update status to\n**DESIGN_REJECTED**;
|
||||||
|
else (other stages)
|
||||||
|
:Update status to\n**NEEDS_CHANGES**;
|
||||||
|
endif
|
||||||
else (no)
|
else (no)
|
||||||
:Keep status as **OPEN**;
|
:Keep status as **OPEN** or **UNDER_REVIEW**;
|
||||||
endif
|
endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,208 @@
|
||||||
|
@startuml workflow-marker-extraction
|
||||||
|
!theme plain
|
||||||
|
title Workflow Marker Extraction with Regex Pattern Matching
|
||||||
|
|
||||||
|
start
|
||||||
|
|
||||||
|
:Discussion file staged\n(feature.discussion.md,\ndesign.discussion.md, etc);
|
||||||
|
|
||||||
|
:workflow.py reads file content;
|
||||||
|
|
||||||
|
partition "Parse Comments" {
|
||||||
|
:Split file into lines;
|
||||||
|
|
||||||
|
repeat
|
||||||
|
:Read next line;
|
||||||
|
|
||||||
|
if (Line is HTML comment?) then (yes)
|
||||||
|
:Skip (metadata);
|
||||||
|
else if (Line is heading?) then (yes)
|
||||||
|
:Skip (structure);
|
||||||
|
else (participant comment)
|
||||||
|
:Extract participant name\n(before first ":");
|
||||||
|
|
||||||
|
note right
|
||||||
|
**Participant Format:**
|
||||||
|
- Rob: Comment text...
|
||||||
|
- Sarah: Comment text...
|
||||||
|
- AI_Claude: Comment text...
|
||||||
|
|
||||||
|
Names starting with "AI_"
|
||||||
|
are excluded from voting if
|
||||||
|
allow_agent_votes: false
|
||||||
|
end note
|
||||||
|
|
||||||
|
partition "Extract Structured Markers" {
|
||||||
|
:Apply regex patterns\nto comment text;
|
||||||
|
|
||||||
|
if (**DECISION**: found?) then (yes)
|
||||||
|
:Pattern: (?:\\*\\*)?DECISION(?:\\*\\*)?\n\\s*:\\s*(.+?)(?=\\*\\*|VOTE:|$);
|
||||||
|
:Extract decision text;
|
||||||
|
:Store: {
|
||||||
|
participant: "Rob",
|
||||||
|
decision: "text...",
|
||||||
|
rationale: "",
|
||||||
|
supporters: []
|
||||||
|
};
|
||||||
|
endif
|
||||||
|
|
||||||
|
if (**QUESTION**: found?) then (yes)
|
||||||
|
:Pattern: (?:\\*\\*)?(?:QUESTION|Q)(?:\\*\\*)?\n\\s*:\\s*(.+?)(?=\\*\\*|VOTE:|$);
|
||||||
|
:Extract question text;
|
||||||
|
:Store: {
|
||||||
|
participant: "Rob",
|
||||||
|
question: "text...",
|
||||||
|
status: "OPEN"
|
||||||
|
};
|
||||||
|
endif
|
||||||
|
|
||||||
|
if (**ACTION**: found?) then (yes)
|
||||||
|
:Pattern: (?:\\*\\*)?(?:ACTION|TODO)(?:\\*\\*)?\n\\s*:\\s*(.+?)(?=\\*\\*|VOTE:|$);
|
||||||
|
:Extract action text;
|
||||||
|
:Search for @mention in text;
|
||||||
|
:Store: {
|
||||||
|
participant: "Rob",
|
||||||
|
action: "text...",
|
||||||
|
assignee: "Sarah",
|
||||||
|
status: "TODO"
|
||||||
|
};
|
||||||
|
endif
|
||||||
|
|
||||||
|
if (Line ends with "?") then (yes)
|
||||||
|
:Auto-detect as question;
|
||||||
|
note right
|
||||||
|
Fallback heuristic:
|
||||||
|
If no explicit marker but
|
||||||
|
line ends with "?",
|
||||||
|
treat as question
|
||||||
|
end note
|
||||||
|
endif
|
||||||
|
|
||||||
|
if (@mention found?) then (yes)
|
||||||
|
:Extract @mentions;
|
||||||
|
:Store in "Awaiting Replies" list;
|
||||||
|
endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VOTE: line found?) then (yes)
|
||||||
|
:Extract vote value:\nREADY|CHANGES|REJECT;
|
||||||
|
:Store latest vote per participant;
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
repeat while (More lines?) is (yes)
|
||||||
|
-> no;
|
||||||
|
}
|
||||||
|
|
||||||
|
partition "Generate Summary Sections" {
|
||||||
|
:Format Decisions section:
|
||||||
|
- Group by participant
|
||||||
|
- Number sequentially
|
||||||
|
- Include rationale if present;
|
||||||
|
|
||||||
|
:Format Open Questions section:
|
||||||
|
- List unanswered questions
|
||||||
|
- Track by participant
|
||||||
|
- Mark status (OPEN/PARTIAL);
|
||||||
|
|
||||||
|
:Format Action Items section:
|
||||||
|
- Group by status (TODO/ASSIGNED/DONE)
|
||||||
|
- Show assignees
|
||||||
|
- Link to requesters;
|
||||||
|
|
||||||
|
:Format Awaiting Replies section:
|
||||||
|
- Group by @mentioned person
|
||||||
|
- Show context of request
|
||||||
|
- Track unresolved mentions;
|
||||||
|
|
||||||
|
:Format Votes section:
|
||||||
|
- Count by value (READY/CHANGES/REJECT)
|
||||||
|
- List latest vote per participant
|
||||||
|
- Exclude AI votes if configured;
|
||||||
|
|
||||||
|
:Format Timeline section:
|
||||||
|
- Chronological order (newest first)
|
||||||
|
- Include status changes
|
||||||
|
- Summarize key events;
|
||||||
|
}
|
||||||
|
|
||||||
|
:Update marker blocks in .sum.md:
|
||||||
|
<!-- SUMMARY:DECISIONS START -->
|
||||||
|
...
|
||||||
|
<!-- SUMMARY:DECISIONS END -->;
|
||||||
|
|
||||||
|
:Stage updated .sum.md file;
|
||||||
|
|
||||||
|
stop
|
||||||
|
|
||||||
|
legend bottom
|
||||||
|
**Example Input (feature.discussion.md):**
|
||||||
|
|
||||||
|
Rob: The architecture looks solid. **DECISION**: We'll use PostgreSQL
|
||||||
|
for the database. **QUESTION**: Should we use TypeScript or JavaScript?
|
||||||
|
**ACTION**: @Sarah please research auth libraries. Looking forward to
|
||||||
|
feedback. VOTE: CHANGES
|
||||||
|
|
||||||
|
**Extracted Output (.sum.md):**
|
||||||
|
|
||||||
|
<!-- SUMMARY:DECISIONS START -->
|
||||||
|
## Decisions (ADR-style)
|
||||||
|
### Decision 1: We'll use PostgreSQL for the database.
|
||||||
|
- **Proposed by:** @Rob
|
||||||
|
<!-- SUMMARY:DECISIONS END -->
|
||||||
|
|
||||||
|
<!-- SUMMARY:OPEN_QUESTIONS START -->
|
||||||
|
## Open Questions
|
||||||
|
- @Rob: Should we use TypeScript or JavaScript?
|
||||||
|
<!-- SUMMARY:OPEN_QUESTIONS END -->
|
||||||
|
|
||||||
|
<!-- SUMMARY:ACTION_ITEMS START -->
|
||||||
|
## Action Items
|
||||||
|
### TODO (unassigned):
|
||||||
|
- [ ] @Sarah please research auth libraries (suggested by @Rob)
|
||||||
|
<!-- SUMMARY:ACTION_ITEMS END -->
|
||||||
|
|
||||||
|
<!-- SUMMARY:AWAITING START -->
|
||||||
|
## Awaiting Replies
|
||||||
|
### @Sarah
|
||||||
|
- @Rob: ... **ACTION**: @Sarah please research auth libraries ...
|
||||||
|
<!-- SUMMARY:AWAITING END -->
|
||||||
|
endlegend
|
||||||
|
|
||||||
|
note right
|
||||||
|
**Regex Pattern Details:**
|
||||||
|
|
||||||
|
**Decision Pattern:**
|
||||||
|
(?:\\*\\*)?DECISION(?:\\*\\*)?\\s*:\\s*(.+?)
|
||||||
|
(?=\\s*(?:\\*\\*QUESTION|\\*\\*ACTION|VOTE:)|$)
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
- Case-insensitive
|
||||||
|
- Optional markdown bold (**) on both sides
|
||||||
|
- Captures text until next marker or VOTE:
|
||||||
|
- DOTALL mode for multi-line capture
|
||||||
|
|
||||||
|
**Supported Formats:**
|
||||||
|
- DECISION: text
|
||||||
|
- **DECISION**: text
|
||||||
|
- decision: text
|
||||||
|
- **decision**: text
|
||||||
|
end note
|
||||||
|
|
||||||
|
note right
|
||||||
|
**Why Regex Instead of Line-Start Matching?**
|
||||||
|
|
||||||
|
✗ Old approach: `if line.startswith("decision:"):`
|
||||||
|
Problem: Markers embedded mid-sentence fail
|
||||||
|
|
||||||
|
✓ New approach: Regex search anywhere in line
|
||||||
|
Handles: "Good point. **DECISION**: We'll use X."
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
- Natural conversational style
|
||||||
|
- Markdown formatting preserved
|
||||||
|
- Multiple markers per comment
|
||||||
|
- Robust extraction
|
||||||
|
end note
|
||||||
|
|
||||||
|
@enduml
|
||||||
Loading…
Reference in New Issue