[Feature]: Multi-agent isolation protocol — process-level feature context without shared-state races
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 55/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Ít trao đổi
- Công nghệ
- shell
- Lĩnh vực
- documentation, tooling
Hướng nghiên cứu
Bắt đầu với get_feature_paths trong common.sh, sau đó kiểm tra template của skill specify và bố cục tài liệu hiện có. Định nghĩa giao thức đa tác nhân trong docs/multi-agent.md, cập nhật hướng dẫn trong template và đánh giá hành vi tùy chọn của SPECIFY_NO_PERSIST. Công việc được xem là hoàn tất khi workflow được ghi trong tài liệu và template tránh việc ghi trực tiếp vào feature.json, đồng thời vẫn giữ nguyên các trường hợp tương thích ngược đã nêu.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Problem Statement
When multiple AI agents run Spec Kit pipelines concurrently within the same repository checkout (e.g., Antigravity subagents, Claude Code sub-agents, or parallel Cursor Composer tabs), they share a single .specify/feature.json file as their feature context pointer. This creates a write-write race condition:
Timeline:
t0 Agent-A: SPECIFY_FEATURE_DIRECTORY="specs/003-auth" → setup-plan.sh
→ get_feature_paths() persists "specs/003-auth" to feature.json ✓
t1 Agent-B: SPECIFY_FEATURE_DIRECTORY="specs/004-perf" → setup-tasks.sh
→ get_feature_paths() persists "specs/004-perf" to feature.json ← overwrites A's value
t2 Agent-A: (new process, no env var) → check-prerequisites.sh
→ reads feature.json → resolves "specs/004-perf" ← WRONG FEATURE
The root issue: get_feature_paths() in common.sh (L191-192) always persists SPECIFY_FEATURE_DIRECTORY back to feature.json unless the caller explicitly passes --no-persist. Since most scripts (setup-plan.sh, setup-tasks.sh) call get_feature_paths without --no-persist, every agent invocation silently overwrites the shared singleton.
Impact
- Silent cross-contamination: Agent B's plan/tasks get written into Agent A's feature directory (or vice versa) without any error signal.
- Non-reproducible failures: The behavior depends on timing — sometimes it works, sometimes it doesn't, making debugging extremely difficult.
- Blocks multi-agent orchestration: Features like
/speckit-implement-waves(#3507), which propose running phases in parallel subagents, cannot work safely without solving this shared-state problem first.
Real-world reproduction
We encountered this in TTZip (a macOS archive utility, 525+ tests, 28 design patterns) while running Antigravity subagents to parallelize a sorting-bugfix TDD suite alongside a 7z compression optimization. Both agents used SPECIFY_FEATURE_DIRECTORY correctly in their own processes, but the persist-on-read side effect in get_feature_paths caused each agent to clobber the other's feature.json entry on every script call.
Root Cause Analysis
The feature resolution chain in common.sh get_feature_paths() (L163-231) has a correct read priority:
1. SPECIFY_FEATURE_DIRECTORY env var (explicit override)
2. .specify/feature.json (persisted fallback)
3. Error (no context)
But it has an unconditional write side effect on the env-var branch (L191-192):
if [[ "$no_persist" != true ]]; then
_persist_feature_json "$repo_root" "$SPECIFY_FEATURE_DIRECTORY"
fi
The --no-persist guard (added in #3025) is a function-level parameter, not an environment-level control. Scripts that are "just resolving paths" but don't know they should pass --no-persist (like setup-plan.sh, setup-tasks.sh) trigger the persist unconditionally.
What already works
Credit to the maintainers — the infrastructure for multi-agent isolation is already in place:
| Mechanism | Status | Issue |
|---|---|---|
SPECIFY_FEATURE_DIRECTORY env var priority |
✅ Working | — |
--no-persist read-only resolution |
✅ Working | #3025 |
CURRENT_BRANCH fallback from feature dir basename |
✅ Working | #3026 |
SPECIFY_INIT_DIR for monorepo project scoping |
✅ Working | — |
| Parser fallback chain (jq → python3 → grep/sed) | ✅ Working | #3304 |
What's missing is the guidance layer: documentation, agent skill instructions, and an environment-level no-persist toggle.
Proposed Solution
1. Official multi-agent documentation (docs/multi-agent.md)
A new document covering:
- The race condition scenario (as above)
- The Multi-Agent Isolation Protocol: always inject
SPECIFY_FEATURE_DIRECTORYper-process, never rely onfeature.jsonfor read - Integration-specific examples (Antigravity subagents, Claude Code sub-agents, Cursor multi-tab, CI matrix)
- FAQ: "Do I need git worktrees?" → No, env-var isolation is sufficient for same-checkout concurrency
2. Update agent skill templates to stop instructing direct feature.json writes
Currently, the specify command template (the upstream equivalent of speckit-specify/SKILL.md) instructs agents to:
Persist the resolved path to
.specify/feature.json:{"feature_directory": "<resolved feature dir>"}
This instruction should be replaced with:
Pass the resolved feature directory to downstream commands via
SPECIFY_FEATURE_DIRECTORYenvironment variable prefix. Example:SPECIFY_FEATURE_DIRECTORY="specs/003-auth" .specify/scripts/bash/setup-plan.sh --json
The feature.json persistence should remain as an automatic side effect of get_feature_paths() for single-agent backward compatibility, but agents should not be told to write it directly (which bypasses the script's own idempotency guards in _persist_feature_json).
3. (Optional) SPECIFY_NO_PERSIST environment variable
Add an environment-level equivalent of the --no-persist function parameter:
# In get_feature_paths(), after the --no-persist argument check (L167-171):
if [[ "${SPECIFY_NO_PERSIST:-}" == "1" || "${SPECIFY_NO_PERSIST:-}" == "true" ]]; then
no_persist=true
fi
This allows CI pipelines and agent orchestrators to set SPECIFY_NO_PERSIST=1 globally, ensuring that no script invocation can accidentally write feature.json — even scripts that don't pass --no-persist internally.
Backward Compatibility
This proposal is fully backward compatible:
| Scenario | Before | After |
|---|---|---|
| Single agent, no env var | Reads feature.json |
Identical behavior |
| Single agent, with env var | Reads env var, persists to feature.json |
Identical behavior |
| Multi-agent, each sets env var | Race on feature.json (bug) |
Each agent's reads are short-circuited by env var; persistence is harmless |
Multi-agent + SPECIFY_NO_PERSIST=1 |
N/A | No feature.json writes at all |
specify integration upgrade |
Overwrites managed files | docs/multi-agent.md is not in manifest; protocol rules live in user-space |
No existing scripts, templates, or workflows change behavior. The persist side effect is still there (it's a "last writer wins" overwrite that's harmless when every reader uses env vars). SPECIFY_NO_PERSIST is strictly additive.
Reference Implementation
We've been running this protocol in production at TTZip with Antigravity (Google DeepMind's agentic coding tool) subagents. Our implementation consists of:
- Project-level rule file (
.agents/rules/speckit-multiagent.md): Instructs all agents to injectSPECIFY_FEATURE_DIRECTORYper-process and never read/writefeature.jsondirectly. - Global user rule: Gates (hard state machine gating) that prevent any agent from writing production code before spec/plan/tasks artifacts exist under the declared feature directory.
- Concurrent verification: Validated that two agents operating on
specs/003-sorting-fix/andspecs/006-7z-conquest/simultaneously produce zero cross-contamination.
The protocol adds zero overhead to single-agent workflows and requires no upstream code changes to function — it's purely a documentation and guidance contribution. The optional SPECIFY_NO_PERSIST env var is a small, additive improvement to common.sh.
Related Issues
- #3507 —
/speckit-implement-waves: Needs this isolation protocol as a prerequisite for safe parallel phase execution - #1476 — Git worktree isolation: Our approach is complementary (env-var isolation within a single checkout vs. filesystem isolation across worktrees)
- #3025 —
--no-persistfor read-only resolution: Foundation we build on - #3026 —
CURRENT_BRANCHfallback: Foundation we build on - #752 — Claude Code subagent feature execution: Would benefit from this protocol
Component
Core scripts (common.sh), Documentation, Agent skill templates
- Ngôn ngữ chính
- Python
- Star
- 138k
- Fork
- 12.4k
- Merge trung bình
- 3 ngày 6 giờ
- Pull request đã merge (30 ngày)
- 136
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của github/spec-kit
-
enhancement needs-triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
-
enhancement needs-triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
-
enhancement needs-triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
-
[Feature]: 给 slug 添加默认值 Đang mởenhancement needs-triage triage-can-wait
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
-
extension-submission triage-can-wait
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
Tất cả issue của github/spec-kit
Issue tương tự
-
documentation help wanted
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 90/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 90/100
simonw/sqlite-utils#872 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100