diff --git a/docs/ai-provider-fallback.puml b/docs/ai-provider-fallback.puml new file mode 100644 index 0000000..65203a0 --- /dev/null +++ b/docs/ai-provider-fallback.puml @@ -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 diff --git a/docs/commit-workflow.puml b/docs/commit-workflow.puml index 150da21..d91b9ee 100644 --- a/docs/commit-workflow.puml +++ b/docs/commit-workflow.puml @@ -8,7 +8,10 @@ participant "pre-commit hook" as hook participant "runner.py" as runner participant "config.py" as config 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 database ".git index" as index @@ -35,22 +38,57 @@ loop For each staged file activate patcher 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 - alt API Success - claude -> patcher: Return unified diff\n(wrapped in markers) + alt Claude produces diff + 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: git apply --3way patcher -> index: Stage generated file patcher -> runner: Success - else API Overload/Error - claude -> patcher: Error response - patcher -> patcher: Log error to stderr - patcher -> runner: Skip this file + else Claude non-diff output + 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 -> runner: Skip this file + end + end end - deactivate claude deactivate patcher end @@ -73,15 +111,38 @@ git -> index: Create commit git -> Developer: Commit successful 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 Saves debug artifacts to .git/ai-rules-debug/ - for troubleshooting + for troubleshooting: + - *.raw.out + - *.clean.diff + - *.sanitized.diff + - *.final.diff end note note right of workflow Always exits 0 (non-blocking) + + Extracts structured markers: + - **DECISION**: text + - **QUESTION**: text + - **ACTION**: @assignee text end note @enduml diff --git a/docs/diagrams-README.md b/docs/diagrams-README.md index 1e5f151..1547398 100644 --- a/docs/diagrams-README.md +++ b/docs/diagrams-README.md @@ -39,18 +39,18 @@ plantuml -tsvg docs/*.puml --- -### 2. **commit-workflow.puml** -**Sequence diagram** of what happens during `git commit`. +### 2. **commit-workflow.puml** ⭐ UPDATED +**Sequence diagram** of what happens during `git commit` with multi-provider fallback. **Shows:** - Pre-commit hook execution - runner.py orchestration -- AI API calls +- Multi-provider AI fallback (claude → codex → gemini) - Patch generation and application -- Vote processing +- Vote processing with marker extraction - 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** -**Detailed flowchart** of AI patch generation and application. +### 4. **patcher-pipeline.puml** ⭐ UPDATED +**Detailed flowchart** of AI patch generation and application with provider fallback. **Shows:** -- Prompt building -- AI command execution +- Prompt building with model hints +- Multi-provider fallback logic (claude → codex → gemini) +- Codex JSON parsing - Patch extraction (with markers) - Patch sanitization - git apply strategies (strict → 3-way → fallback) - Debug artifact saving - 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** -**Voting and promotion logic** for feature discussions. +### 5. **voting-system.puml** ⭐ UPDATED +**Voting and promotion logic** for multi-stage feature discussions. **Shows:** - Vote parsing from discussion files - Eligible voter calculation -- Promotion thresholds (READY_FOR_IMPLEMENTATION) -- Rejection logic +- Stage-specific promotion thresholds (READY_FOR_DESIGN, READY_FOR_IMPLEMENTATION, etc.) +- Rejection logic per stage - 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 ### Automation Pipeline ``` -Developer commits → Pre-commit hook → runner.py → patcher.py → Claude API - → config.py → .ai-rules.yml +Developer commits → Pre-commit hook → runner.py → patcher.py → Multi-Provider AI + → config.py → .ai-rules.yml (claude → codex → gemini) → workflow.py → summary.py + (regex marker extraction) ``` -### File Processing +### File Processing (Multi-Stage) ``` request.md (edited) → AI generates → feature.discussion.md (created/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 @@ -171,9 +224,21 @@ Patch fails → Save debug artifacts → Log error → Continue 3. Review **commit-workflow.puml** for execution order ### Understanding Status Transitions -1. See **voting-system.puml** for promotion logic -2. Check **file-lifecycle.puml** for state machine -3. Review discussion file YAML headers for thresholds +1. See **discussion-stages.puml** for complete multi-stage flow +2. See **voting-system.puml** for promotion logic per stage +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 | | 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 | -| 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 | | Error Handling | ✅ Complete | commit-workflow.puml | diff --git a/docs/discussion-stages.puml b/docs/discussion-stages.puml new file mode 100644 index 0000000..ac135c1 --- /dev/null +++ b/docs/discussion-stages.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 diff --git a/docs/patcher-pipeline.puml b/docs/patcher-pipeline.puml index 278a96b..3a0f673 100644 --- a/docs/patcher-pipeline.puml +++ b/docs/patcher-pipeline.puml @@ -10,32 +10,66 @@ start - Source file diff (staged changes) - Source file full content - Target file current content -- Generation instructions from rules; +- Generation instructions from rules +- Model hint (fast/quality) if specified; -:Call AI via shell command -(configured via git config or env); +partition "Multi-Provider Fallback" { + :Try Provider 1: Claude CLI; -if (AI returned output?) then (yes) - if (Output contains\n"API Error: Overloaded"?) then (yes) - :Raise PatchGenerationError\n"Claude API is overloaded"; - stop - endif - - :Save raw output to\n.git/ai-rules-debug/*.raw.out; - - if (Output contains\n<<>>?) then (yes) - :Extract content between\nSTART and END markers; - else (no) - if (Output contains\n"diff --git"?) then (yes) - :Extract from\n"diff --git" onward; - else (no) - :Raise "AI output did not contain a diff"; + if (Output contains\n"API Error: Overloaded"?) then (yes) + :Raise PatchGenerationError\n"Claude API is overloaded"; stop 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; + +if (Output contains\n<<>>?) then (yes) + :Extract content between\nSTART and END markers; else (no) - :Raise "AI command failed"; - stop + if (Output contains\n"diff --git"?) then (yes) + :Extract from\n"diff --git" onward; + else (no) + :Raise "AI output did not contain a diff"; + stop + endif endif :Save to *.clean.diff; @@ -87,6 +121,17 @@ endif stop 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:** .git/ai-rules-debug/ diff --git a/docs/voting-system.puml b/docs/voting-system.puml index 0339ec9..f8628a5 100644 --- a/docs/voting-system.puml +++ b/docs/voting-system.puml @@ -44,15 +44,28 @@ partition "Promotion Logic (AI-powered)" { :Count CHANGES votes (neutral); if (READY threshold met AND\nREJECT threshold NOT met?) then (yes) - :Update status to\n**READY_FOR_IMPLEMENTATION**; - - if (implementation_gate output defined?) 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**; :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 else if (REJECT threshold met AND\nREADY threshold NOT met?) then (no) - :Update status to\n**FEATURE_REJECTED**; + if (Current stage == feature?) then (yes) + :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) - :Keep status as **OPEN**; + :Keep status as **OPEN** or **UNDER_REVIEW**; endif } diff --git a/docs/workflow-marker-extraction.puml b/docs/workflow-marker-extraction.puml new file mode 100644 index 0000000..c1e0212 --- /dev/null +++ b/docs/workflow-marker-extraction.puml @@ -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: + +... +; + +: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):** + + + ## Decisions (ADR-style) + ### Decision 1: We'll use PostgreSQL for the database. + - **Proposed by:** @Rob + + + + ## Open Questions + - @Rob: Should we use TypeScript or JavaScript? + + + + ## Action Items + ### TODO (unassigned): + - [ ] @Sarah please research auth libraries (suggested by @Rob) + + + + ## Awaiting Replies + ### @Sarah + - @Rob: ... **ACTION**: @Sarah please research auth libraries ... + +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