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:
rob 2025-11-02 13:05:00 -04:00
parent 0601117371
commit 038dbe8a3e
7 changed files with 765 additions and 58 deletions

View File

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

View File

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

View File

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

148
docs/discussion-stages.puml Normal file
View File

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

View File

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

View File

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

View File

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