16 KiB
VC Feedback on Multi-Repo Contributor Workflow
Date: 2025-11-03
Context: Response to docs/contributor-workflow-analysis.md
From: VC Team (AI-supervised issue workflow system)
Executive Summary
Overall Assessment: The multi-repo design is sound and well-thought-out. VC can adopt it post-bootstrap with minimal disruption.
Key Concerns:
- Library API stability - Must remain transparent to library consumers
- Cross-repo dependency resolution - Critical for VC's blocker-first prioritization
- Performance - Hydration caching needed for VC's polling loop
- Namespace collisions - Recommend Option B (global uniqueness)
Current Status: VC uses Beads v0.17.7 as a library, single-repo model, bootstrap phase (pre-contributors).
1. VC's Context & Usage Patterns
How VC Uses Beads
Architecture:
- Beads as library:
beadsLib.NewSQLiteStorage(".beads/vc.db") - Extension model: VC adds tables (
vc_mission_state,vc_agent_events) - Single repo:
.beads/vc.db+.beads/issues.jsonl - Heavy use of ~20 library methods (GetIssue, CreateIssue, GetReadyWork, etc.)
Key Workflows:
- Blocker-first prioritization -
GetReadyWork()sorts by discovered:blocker label first - Atomic claiming -
UPDATE issues SET status='in_progress' WHERE status='open' - Auto-discovery - AI analysis creates issues with
discovered:blockeranddiscovered:relatedlabels - Self-healing - Enters "degraded mode" when
baseline-failureissues exist - Executor exclusion -
no-auto-claimlabel prevents auto-claiming
Performance Profile:
- Polling loop:
GetReadyWork()called every 5-10 seconds - Need sub-second response times
- Cannot afford to re-read N JSONL files on every query
2. Impact Assessment
Short-Term (Bootstrap Phase): ✅ MINIMAL
- Multi-repo is opt-in with backwards-compatible defaults
- VC continues with single
.beads/vc.dband.beads/issues.jsonl - No changes needed during bootstrap
Medium-Term (Post-Bootstrap): ⚠️ LOW-MEDIUM
Potential use cases:
- Testing isolation: Separate repo for experimental executor features
- Multi-contributor: External contributors use
~/.beads-planning/
Concerns:
- Cross-repo dependency resolution must work transparently
- Atomic claiming must preserve ACID guarantees
- Performance impact of multi-repo hydration
Long-Term (Self-Hosting): ✅ BENEFICIAL
- Natural fit for VC's multi-contributor future
- Prevents PR pollution from contributor planning
- Aligns with VC's goal of becoming self-hosting
3. Critical Design Questions
Q1. Library API Stability ⚠️ CRITICAL
Question: Is this a library API change or pure CLI feature?
Context: VC uses beadsLib.NewSQLiteStorage() and expects single JSONL file.
What we need to know:
- Does
NewSQLiteStorage()API change? - Is hydration transparent at library level?
- Or is multi-repo purely a
bdCLI feature?
Recommendation:
// Backwards-compatible: continue to work with no changes
store, err := beadsLib.NewSQLiteStorage(".beads/vc.db")
// Multi-repo should be configured externally (.beads/config.toml)
// and hydrated transparently by the storage layer
// If API must change, provide opt-in:
cfg := beadsLib.Config{
Primary: ".beads/vc.db",
Additional: []string{"~/.beads-planning"},
}
store, err := beadsLib.NewStorageWithConfig(cfg)
Q2. Cross-Repo Dependencies ⚠️ CRITICAL
Question: How does GetReadyWork() handle cross-repo dependencies?
Context: VC's executor relies on dependency graph to find ready work.
Example scenario:
canonical repo (.beads/vc.db):
vc-100 (open, P0) - ready work
planning repo (~/.beads-planning):
vc-101 (open, P1, discovered:blocker) - ready work
vc-102 (open, P2) depends on vc-100 ← cross-repo dependency
Expected results:
GetReadyWork() returns [vc-101, vc-100] ← blocker-first, then priority
(excludes vc-102 - blocked by vc-100)
What we need:
- Hydration layer builds unified dependency graph across all repos
GetReadyWork()respects cross-repo dependencies- Performance acceptable for frequent polling
Recommendation: Document cross-repo dependency behavior clearly and provide test cases.
Q3. Atomic Operations Across Repos ⚠️ CRITICAL
Question: Are writes atomic when multiple repos are hydrated?
Context: VC's executor uses atomic claiming:
// Must be atomic even if issue comes from planning repo
UPDATE issues SET status = 'in_progress', executor_id = ?
WHERE id = ? AND status = 'open'
What we need to know:
- If multiple repos hydrate into single
.beads/vc.db, are writes atomic? - How does hydration layer route writes back to correct JSONL?
- Are there race conditions between multiple processes?
Recommendation: Preserve ACID guarantees. Writes to hydrated database should be transparently routed to correct JSONL with transactional semantics.
Q4. Visibility States vs Issue Status ⚠️ MEDIUM
Question: Are visibility and status orthogonal?
Context: VC uses status: open | in_progress | closed extensively.
From document:
{
"status": "open", // ← VC's current field
"visibility": "local", // ← New field proposed
...
}
What we need to know:
- Can an issue be
status: in_progressandvisibility: local? - Does
GetReadyWork()filter by visibility? - Is this a breaking schema change?
Recommendation: Clarify orthogonality and provide migration guide.
Q5. Performance - Hydration on Every Query? ⚠️ CRITICAL
Question: Does library-level hydration happen on every GetReadyWork() call?
Context: VC's executor polls every 5-10 seconds.
Performance requirement:
// Executor polling loop
for {
// Must be < 1 second, ideally < 100ms
readyWork, err := store.GetReadyWork(ctx, filter)
if len(readyWork) > 0 {
claimIssue(readyWork[0])
}
time.Sleep(5 * time.Second)
}
Recommendation: Implement smart caching:
type MultiRepoStorage struct {
repos []RepoConfig
cache *HydratedCache
lastSync map[string]time.Time
}
func (s *MultiRepoStorage) GetReadyWork(ctx context.Context) ([]Issue, error) {
// Check if any repo has changed since last sync
for _, repo := range s.repos {
if fileModTime(repo.JSONLPath) > s.lastSync[repo.Path] {
s.rehydrate(repo) // ← Only re-read changed repos
}
}
// Query from cached hydrated database (fast)
return s.cache.GetReadyWork(ctx)
}
Rationale: Cannot afford to re-parse N JSONL files every 5 seconds.
4. Design Feedback & Recommendations
F1. Namespace Collisions ✅ VOTE FOR OPTION B
From document's open question:
- Namespace collisions: If two repos both have
bd-a3f8e9, how to handle?
- Option A: Hash includes repo path
- Option B: Global uniqueness (hash includes timestamp + random) ← VC PREFERS THIS
- Option C: Allow collisions, use source_repo to disambiguate
Rationale:
- VC uses
vc-prefix, Beads usesbd-prefix - Hash-based IDs should be globally unique
- Avoids complexity of repo-scoped namespaces
- Simpler for cross-repo dependencies
- Concern with Option C: How does
bd dep add vc-123 vc-456know which repo'svc-123?
Recommendation: Option B (global uniqueness). Include timestamp + random in hash.
F2. Routing Labels vs Semantic Labels ⚠️ IMPORTANT
From document:
[routing.rules.label]
label = "architecture"
target = "~/.beads-work/architecture"
Concern: VC uses labels for semantic meaning, not routing:
discovered:blocker- auto-generated blocker issuesdiscovered:related- auto-generated related workno-auto-claim- prevent executor from claimingbaseline-failure- self-healing baseline failures
Problem: If Beads uses labels for routing, this conflicts with VC's semantic labels.
Recommendation: Use separate mechanism for routing:
[routing.rules]
# Option 1: Use tags instead of labels
[[routing.rules.tag]]
tag = "architecture"
target = "~/.beads-work/architecture"
# Option 2: Use issue type
[[routing.rules.type]]
type = "design"
target = "~/.beads-work/architecture"
# Option 3: Use explicit category/phase field
[[routing.rules.phase]]
phase = "architecture"
target = "~/.beads-work/architecture"
Rationale: Don't overload labels - they're already a general-purpose tagging mechanism.
F3. Proposal Workflow - Dependency Handling ⚠️ MEDIUM
Question: What happens to dependencies when an issue moves repos?
Scenario:
planning repo:
vc-100 "Explore feature"
vc-101 "Document findings" (depends on vc-100)
Proposal workflow:
bd propose vc-100 # ← Move to canonical
Result:
canonical repo:
vc-100 "Explore feature"
planning repo:
vc-101 "Document findings" (depends on vc-100) ← Cross-repo dep now!
Recommendation: Document this behavior clearly:
- Dependencies survive across repos (stored by ID)
bd readychecks cross-repo dependencies- Provide command:
bd dep tree --all-reposto visualize - Consider warning when
bd proposecreates cross-repo deps
F4. Discovered Issues Routing ⚠️ MEDIUM
Context: VC's analysis phase auto-creates issues with labels:
discovered:blockerdiscovered:related
Question: Which repo do discovered issues go to?
Options:
- Same repo as parent issue ← VC PREFERS THIS
- Always canonical
- Configurable routing
Rationale for Option 1:
- Discovered issues are part of work breakdown
- Should stay with parent issue
- Avoids fragmenting related work across repos
Example:
planning repo:
vc-100 "Explore feature" (status: in_progress)
Analysis phase discovers:
vc-101 "Fix edge case" (discovered:blocker, parent: vc-100)
Expected: vc-101 goes to planning repo (same as vc-100)
F5. Self-Healing Across Repos ⚠️ LOW
Context: VC has special behavior for baseline-failure label:
- Enters "degraded mode"
- Only works on baseline-failure issues until fixed
Question: How does this interact with multi-repo?
Scenario:
canonical repo:
vc-300 (baseline-failure) - tests failing
planning repo:
vc-301 (baseline-failure) - build failing
Expected: Executor sees both, enters degraded mode, works on either
Recommendation: Degraded mode should check ALL repos for baseline-failure labels.
5. Test Scenarios VC Needs to Work
Scenario 1: Cross-Repo Blocker-First Prioritization
canonical repo:
vc-100 (open, P0, no labels) - regular work
planning repo:
vc-101 (open, P3, discovered:blocker) - blocker work
Expected: GetReadyWork() returns [vc-101, vc-100]
(blocker-first, even though vc-101 is P3 in planning repo)
Scenario 2: Cross-Repo Dependencies
canonical repo:
vc-200 (open, P0)
planning repo:
vc-201 (open, P0) depends on vc-200
Expected: GetReadyWork() returns [vc-200]
(vc-201 is blocked by vc-200)
Scenario 3: Atomic Claiming
planning repo:
vc-300 (open, P0)
Executor A: Claims vc-300
Executor B: Tries to claim vc-300 concurrently
Expected: Only one executor succeeds (ACID guarantee)
Write routes back to planning repo's JSONL
Scenario 4: No-Auto-Claim Across Repos
canonical repo:
vc-400 (open, P0, no-auto-claim)
planning repo:
vc-401 (open, P0, no-auto-claim)
Expected: GetReadyWork() excludes both
(no-auto-claim works regardless of repo or visibility)
Scenario 5: Baseline Failure Degraded Mode
canonical repo:
vc-500 (open, P0, baseline-failure)
vc-501 (open, P0) - regular work
planning repo:
vc-502 (open, P0) - regular work
Expected: Executor enters degraded mode
Only works on vc-500 (ignores vc-501 and vc-502)
6. Documentation Requests
For Library Consumers (VC's Needs)
- Migration guide: How to adopt multi-repo for existing single-repo projects
- API stability guarantees: What will/won't break in future versions
- Cross-repo dependency semantics: Detailed behavior and examples
- Performance characteristics: Hydration cost, caching strategy, optimization tips
- Schema changes: Backward compatibility for visibility field
For Multi-Repo Users
- Cross-repo workflow examples: Contributor, multi-phase, multi-persona scenarios
- Proposal workflow: What happens to dependencies, labels, metadata when proposing
- Troubleshooting: Common issues (namespace collisions, sync conflicts, performance)
- Best practices: When to use multi-repo vs single-repo, repo organization patterns
7. Open Questions for Beads Team
Priority 1 - CRITICAL:
- Is this a breaking change to storage library API?
- How does cross-repo dependency resolution work at library level?
- What's the hydration performance model for frequent queries?
- Are atomic operations preserved across multi-repo?
Priority 2 - IMPORTANT:
- Which namespace collision strategy will you choose? (VC votes Option B)
- How will routing interact with semantic labels?
- What's the migration path for library consumers?
Priority 3 - NICE TO HAVE:
- How will discovered issues routing work?
- How will special labels (baseline-failure, no-auto-claim) work across repos?
- Will there be performance monitoring/profiling tools for multi-repo setups?
8. VC's Roadmap for Multi-Repo Adoption
Phase 1: Bootstrap (Current)
- ✅ Stick with single repo (
.beads/vc.db,.beads/issues.jsonl) - ✅ Monitor Beads releases for API changes
- ✅ No code changes needed unless API breaks
Phase 2: Post-Bootstrap Testing
- 📋 Evaluate multi-repo for isolated executor testing
- 📋 Test cross-repo scenarios (dependencies, claiming, performance)
- 📋 Validate blocker-first prioritization across repos
Phase 3: Self-Hosting with Contributors
- 📋 Adopt multi-repo for contributor workflow
- 📋 Contributors use
~/.beads-planning/ - 📋 Canonical issues stay in
.beads/issues.jsonl - 📋 Executor handles both transparently
9. Summary & Recommendations
For Beads Team:
High Priority:
- ✅ Solution #4 (Separate Repos) is correct - VCS-agnostic, clean isolation
- ⚠️ Library API must remain stable - Transparent hydration for existing consumers
- ⚠️ Cross-repo dependencies are critical - Must work transparently in GetReadyWork()
- ⚠️ Performance matters - Smart caching needed for polling loops
- ✅ Choose Option B for namespaces - Global uniqueness (timestamp + random)
Medium Priority: 6. ⚠️ Don't overload labels for routing - Use separate mechanism (tags/types/phases) 7. ⚠️ Document cross-repo dependency behavior - Especially in proposal workflow 8. ⚠️ Provide migration guide - For library consumers adopting multi-repo
Design is fundamentally sound. VC can adopt post-bootstrap with minimal changes IF library API remains stable.
For VC Team:
Short-term: No action needed. Continue single-repo development.
Medium-term: Create tracking issues:
- Monitor Beads multi-repo feature development
- Evaluate adoption post-bootstrap
- Test cross-repo scenarios with executor
Long-term: Adopt for contributor workflow when self-hosting.
10. Contact & Follow-Up
VC Project: https://github.com/steveyegge/vc Current Beads Version: v0.17.7 VC's Bootstrap Status: Phase 1 (building core executor)
Questions for Beads team? Feel free to ping VC maintainer or open an issue on VC repo for clarification.
Test scenarios needed? VC can provide more detailed test cases for cross-repo scenarios.
Thank you for the thorough design doc! This is exactly the kind of forward-thinking design discussion that helps downstream consumers prepare for changes. 🙏