Implement CrowdCode platform for democratic AI-assisted development#1
Conversation
Co-authored-by: evcatalyst <8740078+evcatalyst@users.noreply.github.com>
Co-authored-by: evcatalyst <8740078+evcatalyst@users.noreply.github.com>
Co-authored-by: evcatalyst <8740078+evcatalyst@users.noreply.github.com>
Co-authored-by: evcatalyst <8740078+evcatalyst@users.noreply.github.com>
Co-authored-by: evcatalyst <8740078+evcatalyst@users.noreply.github.com>
Co-authored-by: evcatalyst <8740078+evcatalyst@users.noreply.github.com>
evcatalyst
left a comment
There was a problem hiding this comment.
Ok, so this is pretty awesome, would like to see a document and overview on how this could be more easily integrated into GitHub repos for other projects, but we will get there eventually - we need a functional prototype. That said, maybe i didn't see it in the code review, but what is the demo app we will start with, did not see that clear. Should be simple but something fun to evolve over time. Also want to know what links to go to for GitHub pages integration, not sure i saw that. Do i need to config GitHub pages?
There was a problem hiding this comment.
Pull request overview
This PR introduces CrowdCode, a comprehensive platform for democratic, AI-assisted software development. The implementation provides a complete architecture for community-driven feature development using GitHub primitives, where users submit feature requests via issues, AI generates implementation PRs, and a PatchPanel voting system determines which features merge to main.
Key changes:
- Complete platform architecture with voting mechanism, dual-track development (main + persistent feature branches), and transparent audit trails
- Four automated GitHub Actions workflows for issue-to-PR generation, vote counting, feature promotion, and branch visibility
- Python scripts for vote validation, PR generation, feature promotion, and dashboard generation
Reviewed changes
Copilot reviewed 22 out of 24 changed files in this pull request and generated 20 comments.
Show a summary per file
| File | Description |
|---|---|
ARCHITECTURE.md |
Core platform architecture defining AI as contributor, democratic governance, and dual-track code evolution |
scripts/validate-votes.py |
Vote counting logic with PatchPanel member validation and promotion criteria checking |
scripts/promote-feature.py |
Feature promotion script that merges approved PRs and updates labels |
scripts/generate-feature-pr.py |
Issue parsing and PR scaffolding (AI integration ready for Phase 2) |
scripts/generate-dashboard.py |
Feature metadata aggregation for public dashboard |
requirements.txt |
Python dependencies (PyGithub, PyYAML) |
.github/workflows/crowdcode-vote-counting.yml |
Hourly vote counting workflow with reaction and review aggregation |
.github/workflows/crowdcode-issue-to-pr.yml |
Daily issue-to-PR generation workflow |
.github/workflows/crowdcode-feature-promotion.yml |
Daily feature promotion workflow |
.github/workflows/crowdcode-branch-visibility.yml |
Weekly dashboard generation workflow |
.github/crowdcode-config.yml |
Platform configuration with voting thresholds and merge settings |
.github/PATCHPANEL_MEMBERS.json |
Voter registry with physical code support structure |
.github/ISSUE_TEMPLATE/feature-request.yml |
Structured feature request form with acceptance criteria fields |
docs/VOTING_MECHANISM.md |
Multi-phase governance strategy and physical code redemption design |
docs/WORKFLOW_DESIGN.md |
Detailed workflow specifications with error handling |
docs/ROADMAP.md |
Evolution plan from ShelfSignals pilot to marketplace app |
docs/REPO_STRUCTURE.md |
Template repository structure and integration guide |
docs/GETTING_STARTED.md |
Setup checklist and troubleshooting guide |
README.md |
Platform overview with quick start and philosophy |
QUICK_REFERENCE.md |
Single-page reference for voters and feature requesters |
IMPLEMENTATION_SUMMARY.md |
Comprehensive delivery summary and status |
CONTRIBUTING.md |
Contribution guidelines using CrowdCode itself meta-recursively |
LICENSE |
MIT License |
.gitignore |
Python and IDE ignore patterns |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| total_votes = votes['total'] | ||
|
|
||
| if total_votes < quorum: | ||
| return False, f"Quorum not met ({total_votes}/{quorum})" | ||
|
|
||
| # Calculate approval rate from decisive votes only (exclude 'review') | ||
| decisive_votes = votes['approve'] + votes['reject'] | ||
| if decisive_votes == 0: | ||
| return False, "No decisive votes (only review votes)" | ||
|
|
||
| approval_rate = votes['approve'] / decisive_votes |
There was a problem hiding this comment.
The approval rate calculation uses only decisive votes (approve + reject), but the quorum check uses total votes including review votes. This creates an inconsistency where a PR could meet quorum with only review votes but fail to promote due to no decisive votes. Consider also checking quorum against decisive votes, or document this behavior explicitly in the voting mechanism documentation.
| text = text.lower() | ||
| text = re.sub(r'[^\w\s-]', '', text) | ||
| text = re.sub(r'[\s_-]+', '-', text) | ||
| text = re.sub(r'^-+|-+$', '', text) |
There was a problem hiding this comment.
The slugify function has a potential issue where consecutive special characters could result in empty slugs. For example, if the title is "[FEATURE] !!!" after removing non-word characters and replacing spaces, it would become an empty string. Consider adding a fallback to generate a slug from the issue number if the result is empty: return text[:50] or f"feature-{issue_number}"
| text = re.sub(r'^-+|-+$', '', text) | |
| text = re.sub(r'^-+|-+$', '', text) | |
| if not text: | |
| # Fallback to a non-empty default if slug is empty after cleaning | |
| return "feature" |
| --- | ||
|
|
||
| **Related Issue**: #{issue.number} | ||
| **Branch**: Will be created on merge |
There was a problem hiding this comment.
The script generates a branch name but doesn't actually create the branch or PR yet (noted as Phase 2). However, the PR description generation references "Branch: Will be created on merge" which is confusing. When the actual branch creation is implemented, the branch should exist before the PR, so this message will be inaccurate. Consider updating the placeholder message to be clearer about the current implementation state.
| **Branch**: Will be created on merge | |
| **Branch**: Not yet created (branch automation will be added in a future phase) |
|
|
||
| for line in body.split('\n'): | ||
| line = line.strip() | ||
| if line.startswith('### '): | ||
| current_section = line[4:].strip() | ||
| sections[current_section] = [] | ||
| elif current_section and line: | ||
| sections[current_section].append(line) | ||
|
|
||
| # Join multi-line sections | ||
| for key in sections: | ||
| sections[key] = '\n'.join(sections[key]) | ||
|
|
There was a problem hiding this comment.
The parse_issue_body function assumes section headers start with "### " but this is fragile if the issue template format changes. The function silently loses information if sections aren't recognized. Consider validating against expected section names from the template, or logging warnings when expected sections are missing to help debug template format issues.
| for line in body.split('\n'): | |
| line = line.strip() | |
| if line.startswith('### '): | |
| current_section = line[4:].strip() | |
| sections[current_section] = [] | |
| elif current_section and line: | |
| sections[current_section].append(line) | |
| # Join multi-line sections | |
| for key in sections: | |
| sections[key] = '\n'.join(sections[key]) | |
| for line in body.split('\n'): | |
| raw_line = line | |
| line = line.strip() | |
| # Treat any Markdown header (e.g., ##, ###, ####) as a section header. | |
| header_match = re.match(r'^(#+)\s+(.*)', line) | |
| if header_match: | |
| header_level = len(header_match.group(1)) | |
| header_text = header_match.group(2).strip() | |
| # Warn if the header level is not the expected "###" to help | |
| # detect template format changes, but still parse it. | |
| if header_level != 3: | |
| print( | |
| f"Warning: Unexpected header level (#{header_level}) " | |
| f"for section '{header_text}'. Expected level 3 (###). " | |
| f"Original line: {raw_line!r}", | |
| file=sys.stderr, | |
| ) | |
| current_section = header_text | |
| if current_section not in sections: | |
| sections[current_section] = [] | |
| elif current_section and line: | |
| sections[current_section].append(line) | |
| # Join multi-line sections | |
| for key in sections: | |
| sections[key] = '\n'.join(sections[key]) | |
| # If the body is non-empty but no sections were parsed, emit a warning to | |
| # help debug potential template format issues. | |
| if body and body.strip() and not sections: | |
| print( | |
| "Warning: No sections were parsed from the issue body. " | |
| "This may indicate that the issue template format has changed.", | |
| file=sys.stderr, | |
| ) |
| 'status': 'branch-only' | ||
| }) | ||
| except ValueError: | ||
| pass |
There was a problem hiding this comment.
The dashboard generation logic parses branch names assuming the format "crowdcode/feature-{number}-{slug}" but only checks if len(parts) >= 3. If a branch is named "crowdcode/feature-abc" (non-numeric), the int() conversion on line 42 will fail silently in the try/except, but the feature won't be added to the dashboard. Consider logging warnings for malformed branch names to aid debugging.
| pass | |
| print( | |
| f"Warning: malformed feature branch name '{branch.name}' " | |
| "(expected format 'crowdcode/feature-<number>-<slug>')", | |
| file=sys.stderr, | |
| ) |
|
|
||
| import os | ||
| import sys | ||
| import json |
There was a problem hiding this comment.
Import of 'json' is not used.
| import json |
| import json | ||
| import yaml | ||
| from github import Github | ||
| from datetime import datetime |
There was a problem hiding this comment.
Import of 'datetime' is not used.
| from datetime import datetime |
| 'status': 'branch-only' | ||
| }) | ||
| except ValueError: | ||
| pass |
There was a problem hiding this comment.
'except' clause does nothing but pass and there is no explanatory comment.
| pass | |
| # Ignore branches where the issue number segment is not an integer | |
| continue |
| - name: Install dependencies | ||
| run: | | ||
| pip install PyGithub openai pyyaml |
There was a problem hiding this comment.
The sample workflow installs dependencies with pip install PyGithub openai pyyaml using floating versions, so any repo that copies this example will execute whatever package versions PyPI serves at run time while holding GITHUB_TOKEN and write permissions. If one of these packages (or a transitive dependency) is compromised, attackers could execute arbitrary code in CI, exfiltrate secrets, or tamper with code before promotion. To reduce this supply-chain risk, recommend and demonstrate installing pinned dependency versions (for example via a committed requirements.txt with exact versions) instead of unversioned pip install in the workflow example.
| - name: Install dependencies | ||
| run: pip install PyGithub openai pyyaml | ||
|
|
||
| - name: Generate PRs from Issues | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: python scripts/generate-feature-pr.py | ||
| ``` | ||
|
|
||
| ### `.github/workflows/crowdcode-vote-counting.yml` | ||
|
|
||
| **Purpose**: Count votes from PatchPanel members | ||
|
|
||
| **Minimal Example**: | ||
| ```yaml | ||
| name: CrowdCode - Vote Counting | ||
|
|
||
| on: | ||
| pull_request_review: | ||
| issue_comment: | ||
| schedule: | ||
| - cron: '0 * * * *' # Hourly | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| pull-requests: write | ||
| issues: write | ||
|
|
||
| jobs: | ||
| count-votes: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - name: Setup Python | ||
| uses: actions/setup-python@v4 | ||
| with: | ||
| python-version: '3.11' | ||
|
|
||
| - name: Install dependencies | ||
| run: pip install PyGithub pyyaml | ||
|
|
||
| - name: Count Votes | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: python scripts/validate-votes.py | ||
| ``` | ||
|
|
||
| ### `.github/workflows/crowdcode-feature-promotion.yml` | ||
|
|
||
| **Purpose**: Merge approved features to main | ||
|
|
||
| **Minimal Example**: | ||
| ```yaml | ||
| name: CrowdCode - Feature Promotion | ||
|
|
||
| on: | ||
| schedule: | ||
| - cron: '0 6 * * *' # Daily at 6 AM UTC | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| pull-requests: write | ||
| contents: write | ||
| issues: write | ||
|
|
||
| jobs: | ||
| promote-features: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 # Full history for merging | ||
|
|
||
| - name: Setup Python | ||
| uses: actions/setup-python@v4 | ||
| with: | ||
| python-version: '3.11' | ||
|
|
||
| - name: Install dependencies | ||
| run: pip install PyGithub pyyaml |
There was a problem hiding this comment.
All three minimal workflow examples in this document use pip install PyGithub [openai] pyyaml without version pinning, which encourages consumers of this template to execute unpinned third-party code in GitHub Actions jobs that run with GITHUB_TOKEN and repository write access. A compromised or typosquatted PyPI package could then run arbitrary code in CI to exfiltrate secrets or push malicious changes. Update these examples to install only pinned dependency versions (e.g., via a requirements.txt checked into the repo) so downstream users adopt reproducible, lower-risk dependency management in their workflows.
Introduces a collaborative development platform where community members submit feature requests via GitHub Issues, AI generates implementation PRs, and a PatchPanel voting system determines which features merge to main. All feature branches remain publicly visible indefinitely.
Architecture
Core Components:
main+ persistentcrowdcode/feature-*branchesPATCH-YYYY-NNNN)Key Files:
ARCHITECTURE.md- System design, data flow, security modeldocs/VOTING_MECHANISM.md- Multi-phase governance strategydocs/ROADMAP.md- Evolution from ShelfSignals pilot to marketplace appGitHub Actions Workflows
Four automated workflows using GitHub primitives:
crowdcode-issue-to-pr.yml(daily 2AM UTC) - Scanscrowdcode:feature-requestissues, generates PRs with feature branchescrowdcode-vote-counting.yml(hourly) - Aggregates votes from PatchPanel members, updates PR status, appliesready-to-promotelabel when threshold metcrowdcode-feature-promotion.yml(daily 6AM UTC) - Squash-merges approved PRs, preserves feature branchescrowdcode-branch-visibility.yml(weekly) - Generates JSON dashboard of all featuresAll workflows support dry-run mode via
workflow_dispatch.Scripts & Configuration
Python utilities (security-scanned, 0 vulnerabilities):
validate-votes.py- Counts decisive votes (approve/(approve+reject)), excludes review-only from approval rategenerate-feature-pr.py- Issue parsing, branch naming, PR scaffolding (AI integration ready)promote-feature.py- Merge orchestration, issue closuregenerate-dashboard.py- Feature metadata aggregationConfiguration:
Issue template with structured fields: feature name, description, use case, acceptance criteria
Documentation
docs/GETTING_STARTED.md- Setup checklist, label creation, troubleshootingdocs/REPO_STRUCTURE.md- Template for CrowdCode-enabled repos, ShelfSignals integrationdocs/WORKFLOW_DESIGN.md- Workflow implementation details, error handlingQUICK_REFERENCE.md- Single-page reference for voters and requestersDesign Decisions
Minimal infrastructure: No external services, databases, or webhooks. Pure GitHub primitives.
Transparency first: Feature branches never deleted, all votes public, complete Git audit trail.
AI as contributor: GitHub Copilot generates proposals in Phase 2. Current implementation provides complete workflow structure with placeholder scripts.
Physical-digital bridge: Code redemption enables exhibition/conference participation without GitHub accounts.
Total: 5,173 lines across 27 files (10 documentation, 4 workflows, 4 scripts, 3 configs).
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.